Linking unmanaged C++ DLL with managed C++ class library DLL
Asked Answered
A

1

8

As in the question Creating simple c++.net wrapper. Step-by-step

I am tring to use C++ classes in .NET but I am having problems building in Visual Studio (2008).

I have an unmanaged class A (C++ compiled with /clr). I created a C++/clr class 'Class1' which wraps A and with matching method delegates to A's methods.

If I include class A's unit source file in the class library project for Class1 (managed) I have no problems everything links and works fine, But I have many unmanaged C++ classes like A and I am tring to put them in a DLL and link that DLL to the managed library (of class wrappers). [I actually don't see a need to link these DLL's together at this point, but the compiler appears to be requiring it, giving the same errors shown below.]

I created VisualC++ / CLR / Class library and added my C++ class (A listed below) and build. [I used the default settings but in the project linker settings I've tried both Register output with yes and no.] There were no errors and the .DLL file was created.

I created VisualC++ / CLR / Class library and created the wrapper class 'Class1' I used all default settings. Under project properties I clicked 'References' 'Add New Reference" and selected the DLL created in the first step.

I get linker errors:

test_NET_library.obj : error LNK2028: unresolved token (0A000009) "public: int __thiscall Z::A::m1(int,int)" (?m1@A@Z@@$$FQAEHHH@Z) referenced in function "public: int __clrcall test_NET_library::Class1::m1(int,int)" (?m1@Class1@test_NET_library@@$$FQ$AAMHHH@Z)
test_NET_library.obj : error LNK2028: unresolved token (0A00000A) "public: int __thiscall Z::A::m2(int,int)" (?m2@A@Z@@$$FQAEHHH@Z) referenced in function "public: int __clrcall test_NET_library::Class1::m2(int,int)" (?m2@Class1@test_NET_library@@$$FQ$AAMHHH@Z)
test_NET_library.obj : error LNK2019: unresolved external symbol "public: int __thiscall Z::A::m1(int,int)" (?m1@A@Z@@$$FQAEHHH@Z) referenced in function "public: int __clrcall test_NET_library::Class1::m1(int,int)" (?m1@Class1@test_NET_library@@$$FQ$AAMHHH@Z)
test_NET_library.obj : error LNK2019: unresolved external symbol "public: int __thiscall Z::A::m2(int,int)" (?m2@A@Z@@$$FQAEHHH@Z) referenced in function "public: int __clrcall test_NET_library::Class1::m2(int,int)" (?m2@Class1@test_NET_library@@$$FQ$AAMHHH@Z)
C:\temp\test_Cpp_CLI\test_NET_library\Debug\test_NET_library.dll : fatal error LNK1120: 4 unresolved externals

The same errors as if I remove A.cpp in the wrapper class library project (the option that works). I don't understand why the build is trying to resolve externals in the first place because this is a library, not a program.

Is there something else I need to add to the wrapper class library project properties or register the DLL of unmanaged classes, or compiler options? Do I also need a .lib file to go with the DLL? (no lib file appears in the projects target directory)

Do I still have to use __declspec(dllexport) [it thought that was only for C style functions not class members.] as in the question: Export Unmanaged Classes from a Visual C++ DLL? even though the unmanaged C++ library is compiled with CLR enabled.

(I did also try compiling as a static library, but I can't figure out how to add the .lib file to the CLR class library project).

My test class is

namespace Z 
{
class A
{
public:

   int m1(int p1, int p2);
   int m2(int p3, int p4);
};
};

with the implementation:

#include "A.h"
namespace Z 
{
int A::m1(int p1, int p2) { return p1+p2; };
int A::m2(int p3, int p4) { return p3 * p4; };
};

And the wrapper class is

#pragma once
#include "../A.h"
using namespace System;
namespace test_NET_library {
 public ref class Class1
 {
 private: Z::A *a;
 public: Class1()
  : a(new Z::A)
   {}
 public: inline int m1(int p1, int p2)
  {  return a->m1(p1,p2);
  };
 public: inline int m2(int p3, int p4)
  {return a->m2(p3,p4);
  };
 };
}

As per the question: C++/CLI Mixed Mode DLL Creation I have also tried:

#pragma managed(push, off) 
#include "../A.h"
#pragma managed(pop)

And also this pushing managed around A.cpp.

Update: As per mcdave's response I removed the /clr this produced a DLL, now how do I make this DLL available to my test_NET_library?

I tried References/Add New Reference, and selected the new this new DLL; and got the message "Could not add reference to file 'C:..\unmanaged_lib.dll' because it is neither .NET assembly or registered ActiveX control.". The DLL was added to the project's file list, but the compiler appears to be ignoring it.

I tried Add/Existing item and selected the new DLL. but .DLL files are not a selectable file type.

Apiculate answered 23/10, 2010 at 3:5 Comment(2)
Try removing /clr from class A's DLL (meaning make it a 'normal' win32 dll) and if this doesn't work update your question.Ire
@mcdave: I did this, but then I don't know how to make test_NET_libary 'aware of' or 'link to' this unmanaged_lib.DLL containing A (see my edit above). It is the same problem I have trying to use unmanaged_lib as a statically linked .lib.Apiculate
I
6

With the few hints from your update I will try two guesses...

  1. When unmanaged_lib is a statically linked lib, have you set the unmanaged_lib project to be a dependency of test_NET_library? (In the Project Explorer window, right-click on test_NET_library, select "Project Dependencies..." and select unmanaged_lib.)
  2. When unmanaged_lib is a DLL, you need to export the class from the DLL by following this answer and also make the test_NET_library depend on the unmanaged_lib project.
Ire answered 7/11, 2010 at 10:10 Comment(1)
Solution 1 worked (normally I use Embarcadero C++Builder, there you simply add the compile .lib file to your project, it is not even necessary to have all the static library projects in your project group (solution), nor necessary to setup dependencies).Apiculate

© 2022 - 2024 — McMap. All rights reserved.