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

Posted

技术标签:

【中文标题】如何将结构传递给 c++ 函数并通过一些修改返回相同的结构?【英文标题】:How to pass a structure to a c++ function and return the same with some modifications? 【发布时间】:2017-05-26 04:02:41 【问题描述】:

我的 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);

我收到以下错误 -

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

无法获取托管类型的地址、大小或声明指向托管类型的指针

【问题讨论】:

您的问题不清楚。这是什么意思:“我不知道如何在 c# 中使用它”?你得到什么错误? 请查看我更新的问题。 【参考方案1】:

你不能像你一样从函数中返回结构,你可以简单地通过引用传递结构(顺便说一句,整个 Windows API 就是这样定义的)。

这里是如何声明结构体,别忘了指明字符集是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 关键字。

【讨论】:

我用 out 关键字尝试了上述方法,效果很好。关于何时使用 out 而不是 ref 的任何规则? 如果我需要修改调用以将结构数组发送到本机代码怎么办?我知道这可以通过将 IntPtr 传递给数组来完成。不完全确定该怎么做。 使用 ref 是您传入和传出数据。在你的问题中是这样的。这是基本的 C#。阅读有关这两个关键字的文档。

以上是关于如何将结构传递给 c++ 函数并通过一些修改返回相同的结构?的主要内容,如果未能解决你的问题,请参考以下文章

如何将值从python传递给c++并返回?

如何将结构数组从 c++ 传递到 c#?

将 C++ 类编组为结构

如何将数组从 c++ 传递给 python 函数并将 python 返回的数组检索到 c++

将 c++ 向量传递给 python 并返回

将结构的枚举传递给其他函数并分配值