Marshalling C ++ struct to C #

I have such a simple structure in unmanaged C ++:

struct Cam { char ip[16]; char login[16]; char pass[16]; char name[16]; }; 

and assembly structure with C #:

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct Cam { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string ip; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string login; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string pass; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string name; } 

When I pass C # struct to C ++ lib by function

 [DllImport("NVRLib.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void AddCameraStruct(Cam cam); ... Cam cam = new Cam(); cam.ip = "192.168.0.232"; cam.login = "admin"; cam.pass = "admin"; cam.name = "kekekeke"; AddCameraStruct(cam); 

and print the passed values ​​in C ++:

 __declspec(dllexport) void AddCameraStruct(Camera cam) { printf(cam.ip); printf("\n"); printf(cam.login); printf("\n"); printf(cam.name); printf("\n"); printf(cam.pass); strcpy(camera[CAM_NUM].ip, cam.ip); strcpy(camera[CAM_NUM].login, cam.login); strcpy(camera[CAM_NUM].pass, cam.pass); strcpy(camera[CAM_NUM].name, cam.name); CAM_NUM++; } 

he prints:

 232 <EMPTY LINE> 192.168.0.232 n 

What am I doing wrong?

+6
source share
2 answers

Update: you wrote:

you were right, I skipped this and the IDE didn’t offer me anything because I also have a camera class in C ++ .. Thanks :)

which I assumed is a copy and paste error. In the example below, this has already been fixed and it works. You don’t know why / if you received errors if your code contained Cam , because it is not a recognized structure (at least in my environment).

Bottom line: the parts of your code that you are showing work. You are using UnmanagedType.ByValTStr , which depends on the selected encoding, which you define as CharSet = CharSet.Ansi , which, in turn, maps to char * in your DLL. This is how it should be marshaled, it’s just right.

I created a test application PInvokeTestDll as follows:

Part of the DLL in Win32's own DLL project:

 #include <atlbase.h> WIN32_DLL_UNMANGLED_API void AddCameraStruct(Camera cam) { USES_CONVERSION; OutputDebugString(A2W(cam.ip)); OutputDebugString(A2W(cam.login)); OutputDebugString(A2W(cam.name)); OutputDebugString(A2W(cam.pass)); } 

In the header file:

 #define WIN32_DLL_UNMANGLED_API extern "C" _declspec(dllexport) struct Camera { char ip[16]; char login[16]; char pass[16]; char name[16]; }; WIN32_DLL_UNMANGLED_API void AddCameraStruct(Camera cam); 

In a C # project:

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct Cam { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string ip; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string login; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string pass; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string name; } class Program { [DllImport(@"PInvokeTestDll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void AddCameraStruct(Cam cam); static void Main(string[] args) { Cam cam = new Cam { ip = "192.168.0.232", login = "admin", pass = "admin", name = "kekekeke" }; AddCameraStruct(cam); } } 

Running this project shows the following in the Output> Debugging window in Visual Studio:

 192.168.0.232adminkekekekeadmin 

As you can see, I renamed the Cam structure to the Camera structure, suggesting that it was a cut and paste error on your side. I also deleted printf statements because you do not see the output during debugging (and OutputDebugString requires LPCWSTR , so the ATL A2W macro).

My guess is that you are not showing the part that actually causes your structure to fail. I assume that it is at the end of C ++, because if the structures are what you typed, it “just works” (it is also “checked”, hovering over the fields of the structure when entering the DLL function during debugging ) I suggest you isolate the problem by doing what I did: create a test project that deals only with marshaling and the prototype of the exported DLL function.

+2
source

After I learned more from your comments,

Change

 __declspec(dllexport) void AddCameraStruct(Camera cam) 

To

 __declspec(dllexport) void AddCameraStruct(Cam cam) 
+1
source

All Articles