gpt4 book ai didi

c# - 将带有字符串数组的 C# 结构传递给 c++ 函数,该函数接受 void * 用于 c# 结构和 char** 用于 c# 字符串数组

转载 作者:行者123 更新时间:2023-11-30 20:56:13 28 4
gpt4 key购买 nike

我想将带有字符串数组的C# 结构发送到C++ 函数,该函数接受void * 作为c# 结构和char** 作为c# 结构字符串数组成员。

我能够将结构发送到 c++ 函数,但问题是,无法从 c++ 函数访问 c# 结构的字符串数组数据成员。当单独发送字符串数组时,我能够访问数组元素。

示例代码是-

C# Code:

[StructLayout(LayoutKind.Sequential)]
public struct TestInfo
{
public int TestId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public String[] Parameters;
}

[DllImport("TestAPI.dll", CallingConvention = CallingConvention.StdCall, EntryPoint "TestAPI")]
private static extern void TestAPI(ref TestInfo data);

static unsafe void Main(string[] args)
{
TestInfo testinfoObj = new TestInfo();
testinfoObj.TestId = 1;
List<string> names = new List<string>();
names.Add("first");
names.Add("second");
names.Add("third");
testinfoObj.Parameters=names.ToArray();
TestAPI(ref testinfoObj);
}



VC++ Code:

/*Structure with details for TestInfo*/
typedef struct TestInfo
{
int TestId;
char **Parameters;
}TestInfo_t;

//c++ function
__declspec(dllexport) int TestAPI(void *data)
{
TestInfo *cmd_data_ptr= NULL;
cmd_data_ptr = (TestInfo) data;
printf("ID is %d \r\n",cmd_data_ptr->TestId);//Working fine

for(i = 0; i < 3; i++)
printf("value: %s \r\n",((char *)cmd_data_ptr->Parameters)[i]);/*Error-Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt*/
}

在分析内存堆栈时,观察到,当我打印((char *)cmd_data_ptr->Parameters),正在打印第一个数组元素(“first”),但是使用 ((char *)cmd_data_ptr->Parameters)[i],无法访问元素和上述异常即将到来。

结构内存地址包含所有结构元素的地址,但是从c++访问数据时,它只访问字符串数组的第一个元素。

最佳答案

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public String[] Parameters;

是一个内联数组。匹配的 C++ 声明是:

char* Parameters[2];

但是您正试图将其匹配到:

char** Parameters;

那是完全不同的。

您需要手动整理它。在 C# 结构中将 Parameters 声明为 IntPtr。然后使用 Marshal.AllocHGlobal 分配 native 内存以保存指针数组。然后用指向您的字符串的指针填充这些指针。

[StructLayout(LayoutKind.Sequential)]
public struct TestInfo
{
public int TestId;
public IntPtr Parameters;
}

static void Main(string[] args) // no need for unsafe
{
TestInfo testInfo;
testInfo.TestId = 1;
testInfo.Parameters = Marshal.AllocHGlobal(2*Marshal.SizeOf(typeof(IntPtr)));
IntPtr ptr = testInfo.Parameters;
Marshal.WriteIntPtr(ptr, Marshal.StringToHGlobalAnsi("foo"));
ptr += Marshal.SizeOf(typeof(IntPtr));
Marshal.WriteIntPtr(ptr, Marshal.StringToHGlobalAnsi("bar"));
TestAPI(ref testinfoObj);
// now you want to call FreeHGlobal, I'll leave that code to you
}

另一种方法是使用固定的 IntPtr[] 并将其放入 testInfo.Parameters。

关于c# - 将带有字符串数组的 C# 结构传递给 c++ 函数,该函数接受 void * 用于 c# 结构和 char** 用于 c# 字符串数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17654892/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com