2

I have a native dynamic link library written in VC++6 and I do not have access to the source code. I would like to convert it to managed code so that C# can call this library. The problem is that the VC6 library heavily makes use of std::vector and std::string as function parameters and there is no way of marshaling these types into C# directly.

So what I need is a bridge between VC6 and C# and I implemented a VC++2005 wrapper for VC++6.

However, I realized from the reply (by jalf) to the following thread that "VC++6 and VC++2005 have different definitions of std::string (and the compilers may also insert different padding and other changes), and the result is garbage, and/or unpredictable behavior and crashes".

Passing std::string from VC++2005 to VC++6 DLL results in garbage

So now, the big question is, how can I call the VC++6 native library from C#?

I am at a loss and any help is greatly appreciated.

Community
  • 1
  • 1
Lopper
  • 3,499
  • 7
  • 38
  • 57

1 Answers1

2

If you've got access to VC++6, compile the "bridging/wrapper" dll with that. Then, expose functions with types you can P/Invoke from C# such as Char* etc..

BTW, You can probably get a "used" license on eBay or something for cheap.

EDIT:
Here's a sample code for what you've asked (I think...):

[System.Runtime.InteropServices.DllImport("somedll.dll")]
public static extern int Fun1(int n, IntPtr[] lpNames);


//////////////////////////////////////////////////////////////////////////
List<string> strList = new List<string>();

IntPtr[] strPointerArr = new IntPtr[strList.Count];
for(int i=0; i<strList.Count; ++i){
    strPointerArr[i] = System.Runtime.InteropServices.Marshal.StringToHGlobalUni(strList[i]);
}
Fun1(strList.Count, strPointerArr);

//////////////////////////////////////////////////////////////////////////
dtroy
  • 1,187
  • 3
  • 14
  • 21
  • This sounds like a good solution at first but how do you convert this complex type std::vector to something else that can be P/Invoke from C#? – Lopper Nov 27 '09 at 01:49
  • If you just need to pass it, `const char**` (i.e. dynamic array of dynamic arrays of chars) would do the trick (use `CoTaskMemAlloc`, and require the caller to free it). – Pavel Minaev Nov 27 '09 at 01:53
  • What about the other way round where the "bridging/wrapper" dll written in VC++6 wants to pass char** back to C#? In this case, the memory can't be deallocated because C# cannot do this. – Lopper Nov 27 '09 at 02:09
  • You can use the memory allocation functions from Kernerl32.dll: GlobalAlloc, GlobalFree and P\Invoke them – dtroy Nov 27 '09 at 02:31
  • Or even use: Marshal.FreeHGlobal Method. Looking at MSDN, I think it's the same – dtroy Nov 27 '09 at 02:35
  • I haven't done any memory allocation before in C# so I am kind of new to this. Can someone please provide examples of how memory for the following C# type (List) can be allocated for passing to the bridging dll which expects const char** as an argument. And also the code for how to actually pass this? – Lopper Nov 27 '09 at 02:48