Reputation: 11
I am a seasoned software engineer but somewhat new to C#. I have a DLL which is made up of C++ objects with a C interface as shown. I used this C interface because I was not sure if there was a way of accessing C++ entry points in the DLL from my C# application.
__declspec(dllexport) void *Constructor();
__declspec(dllexport) void Destructor(void *pObj);
__declspec(dllexport) int Method(void *pObj, char *pSrcDst, int len);
This is the C code for the above interface.
extern "C" void *Constructor()
{
return (void *)new Object;
}
extern "C" void Destructor(void *pObj)
{
delete (Object *)pObj;
}
extern "C" int Method(void *pObj, char *pSrcDst, int len)
{
if (!pObj) return 0;
return ((Object *)pObj)->Method(pSrcDst, len);
}
So far so good. Now, I need to be able to access this interface from a C# application. From what I have learned I have implemented the following C# interface.
unsafe public class Wrapper
{
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDLL.dll")]
public static extern
IntPtr Constructor();
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDLL.dll")]
public static extern
void Destructor(IntPtr pObj);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDLL.dll")]
public static extern
int Method(IntPtr pObj, [In,Out] byte[] pSrcDst, int len);
And here's the C# code which uses the above interface.
private IntPtr pObject;
public object()
{
pObject = Wrapper.Constructor();
}
~object()
{
Wrapper.Destructor(pObject);
}
public override byte[] method()
{
byte[] bytes = new byte[100];
int converted = Wrapper.Method(pObject, bytes, bytes.length);
return bytes;
}
The code asserts at both the call to Wrapper.Method as well as the Wrapper.Destructor. I assume I am not handling the pointer to the object properly. Any suggestions?
Upvotes: 1
Views: 3148
Reputation: 244757
The most likely problem is that your code doesn't use the correct calling convention. In C++ the default is __cdecl
, but for DllImport
, the default is __stdcall
.
To fix this, specify the calling convention explicitly:
[DllImport("MyDLL.dll", CallingConvention = CallingConvention.Cdecl)]
Upvotes: 3
Reputation: 5005
I was under the impression that the best way to do this sort of thing was using a managed c++/CLI wrapper.
Creating simple c++.net wrapper. Step-by-step
and
http://devmaster.net/forums/topic/7357-how-to-build-a-net-wrapper-for-a-c-library/
look like promising leads.
Upvotes: 1