Please Help -- Link Error in Managed Wrapper
-
Hi All, I'm a developer with most of my experience in MFC, C#. Recently, I've been assigned to a project that has a Borland C++ 6 (OWL) GUI and a VC6.0 DLL that does most of the work. The VC6 DLL has around 1500 functions declared as
extern "C" __stdcall
(1500??!! I know... seriously! :^) ) Now I've been delegated with the job of replacing the BOrland GUI with a new console/GUI mode application (in C#). Hence, I decided to write a Managed C++ wrapper for this native DLL, and then write my application in C#. The downside is that I don't have access to the source code for the VC6 DLL. I felt that a managed c++ DLL project which statically links to the .lib file for the VC6 native DLL might be the best approach. I've created a Managed C++ CLR Class library project, which has a reference to the unmanaged VC6 .lib file (from Project Properties -> Linker -> Input -> Additional Dependencies. I've also added the header file for the DLL to this project. I have created a managed class which wraps all the functions in the unmanaged DLL in a function. Header file#pragma once
#pragma comment(lib, "C:\\Sources\\lib\\native.lib")
#include "..\..\Common\include\native.h"
#include "Common.h"#using <System.dll>
#using <System.Windows.Forms.dll>using namespace System;
using namespace System::Windows::Forms;namespace MC_SAMPDLL
{public ref class MCSAMP { MYRESULT MC\_Func1(int handle, unsigned int timeout) { return ::Func1(handle, timeout); } };
}
For example if the unmanaged function is Func1(), I'm creating a wrapper function MC_Func1(). MCSAMP:: However, when I try to call any unmanaged function from within the managed wrapper, I get linker errors as below
Error 1 error LNK2028: unresolved token (0A000012) "extern "C" enum MYRESULT __stdcall Func1(int,unsigned int)" (?Func1@@$$J18YG?AW4MYRESULT@@HI@Z) referenced in function "private: enum MYRESULT __clrcall MC_SAMPDLL::MCSAMP::MC_Func1(int,unsigned int)" (?MC_Func1@MCSAMP@MC_SAMPDLL@@$$FA$AAM?AW4MYRESULT@@HI@Z) MC_SAMPDLL.obj MC_SAMPDLL
Error 2 error LNK2019: unresolved external symbol "extern "C" enum MYRESULT __stdcall Func1(int,unsigned int)" (?Func1@@$$J18YG?AW4MYRESULT@@HI@Z) referenced in function "private: enum MYRESULT __clrcall MC_SAMPDLL::MCSAMP::MC_Func1(int,unsigned int)" (?MC_Func1@MCSAMP@MC_SAMPDLL@@$$FA$AAM?AW4MYRESULT@@HI@Z) MC_SAMPDLL.obj MC_SAMPDLL
Error 3 fatal error LNK1120: 2 unresolved -
Hi All, I'm a developer with most of my experience in MFC, C#. Recently, I've been assigned to a project that has a Borland C++ 6 (OWL) GUI and a VC6.0 DLL that does most of the work. The VC6 DLL has around 1500 functions declared as
extern "C" __stdcall
(1500??!! I know... seriously! :^) ) Now I've been delegated with the job of replacing the BOrland GUI with a new console/GUI mode application (in C#). Hence, I decided to write a Managed C++ wrapper for this native DLL, and then write my application in C#. The downside is that I don't have access to the source code for the VC6 DLL. I felt that a managed c++ DLL project which statically links to the .lib file for the VC6 native DLL might be the best approach. I've created a Managed C++ CLR Class library project, which has a reference to the unmanaged VC6 .lib file (from Project Properties -> Linker -> Input -> Additional Dependencies. I've also added the header file for the DLL to this project. I have created a managed class which wraps all the functions in the unmanaged DLL in a function. Header file#pragma once
#pragma comment(lib, "C:\\Sources\\lib\\native.lib")
#include "..\..\Common\include\native.h"
#include "Common.h"#using <System.dll>
#using <System.Windows.Forms.dll>using namespace System;
using namespace System::Windows::Forms;namespace MC_SAMPDLL
{public ref class MCSAMP { MYRESULT MC\_Func1(int handle, unsigned int timeout) { return ::Func1(handle, timeout); } };
}
For example if the unmanaged function is Func1(), I'm creating a wrapper function MC_Func1(). MCSAMP:: However, when I try to call any unmanaged function from within the managed wrapper, I get linker errors as below
Error 1 error LNK2028: unresolved token (0A000012) "extern "C" enum MYRESULT __stdcall Func1(int,unsigned int)" (?Func1@@$$J18YG?AW4MYRESULT@@HI@Z) referenced in function "private: enum MYRESULT __clrcall MC_SAMPDLL::MCSAMP::MC_Func1(int,unsigned int)" (?MC_Func1@MCSAMP@MC_SAMPDLL@@$$FA$AAM?AW4MYRESULT@@HI@Z) MC_SAMPDLL.obj MC_SAMPDLL
Error 2 error LNK2019: unresolved external symbol "extern "C" enum MYRESULT __stdcall Func1(int,unsigned int)" (?Func1@@$$J18YG?AW4MYRESULT@@HI@Z) referenced in function "private: enum MYRESULT __clrcall MC_SAMPDLL::MCSAMP::MC_Func1(int,unsigned int)" (?MC_Func1@MCSAMP@MC_SAMPDLL@@$$FA$AAM?AW4MYRESULT@@HI@Z) MC_SAMPDLL.obj MC_SAMPDLL
Error 3 fatal error LNK1120: 2 unresolvedHi, Since I couldn't find any solution to the problem, nor are there any replies here in this forum :(, I finally decided to go in for a C# based P/Invoke method of calling the native DLL. I know it sucks compared to the MC++ wrapper solution, but hey, at least it works! For those who are stuck in a similar situation, they can try using the [PInvoke Interop Assistant]. This is a wonderful open source tool that makes it really simple to create an automated wrapper for native dlls. There are a few articles in MSDN magazine on how to use this tool too. It comes with a command-line interface that allows easy porting of entire header files in the easiest manner possible. Just supply your header files to this tool, and it'll write out almost the entire wrapper declarations. Just to make sure though, you should manually examine all the ported declarations, ensuring that no mistakes are present. Hope this helps someone else, Bharat
'The time has come,' the Walrus said, 'To talk of many things: Of shoes -- and ships -- and sealing wax -- Of cabbages -- and kings -- And why the sea is boiling hot -- And whether pigs have wings.' -- The Walrus and the Carpenter (by Lewis Carroll)