如何将结构传递给c ++函数并通过一些修改返回它?

时间:2017-05-26 04:02:42

标签: c# c++ .net pinvoke

我的c ++函数中有以下结构。

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

以下是我从cpp类中公开的方法 -

extern "C" __declspec(dllexport) Cam* AddCameraStruct1(Cam cam)
{
//modify the cam object
}

以下是我在c#中定义结构和函数的方法。

[StructLayout(LayoutKind.Sequential)]
    internal unsafe 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;
    }

 [DllImport(@"mydll.dll", CallingConvention = CallingConvention.Cdecl)]
    [return: MarshalAs(UnmanagedType.LPStruct)]
    internal static extern IntPtr AddCameraStruct1(DPAPI.Cam*);

我没有得到如何在c#中使用它。如果出现问题,请提示。

unsafe
 {
                DPAPI.Cam cam = new DPAPI.Cam();
                cam.ip = "192.168.0.232";
                cam.login = "admin";
                cam.pass = "admin";
                cam.name = "kekekeke";
                DPAPI.Cam* cam1 = (DPAPI.Cam*)DPAPI.AddCameraStruct1(cam);
}

我收到以下错误 -

指针和固定大小的缓冲区只能在不安全的上下文中使用

不能获取地址,获取大小或声明指向托管类型的指针

1 个答案:

答案 0 :(得分:2)

你不能像你那样从函数返回结构,你只需通过引用传递结构(这就是整个Windows API定义为BTW的方式)。

以下是如何声明结构,不要忘记指出charset是Ansi:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
internal 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;
}

以下是如何声明方法(ref参数类似于使用*):

[DllImport(@"mydll.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void AddCameraStruct1(ref Cam pcam);

以下是如何在C / C ++中声明它:

extern "C" __declspec(dllexport) void AddCameraStruct1(Cam *pcam)
{
  strcpy_s(pcam->name, "hello"); // for example
}

以下是您现在打电话的方式:

var cam = new Cam();
cam.ip = "192.168.0.232";
cam.login = "admin";
cam.pass = "admin";
cam.name = "kekekeke";
AddCameraStruct1(ref cam);
// cam.name is now "hello"

请注意,您的代码中根本不需要使用unsafe关键字。