gpt4 book ai didi

c# - 遍历使用 Marshal.AllocHGlobal() 分配的内存

转载 作者:太空狗 更新时间:2023-10-29 23:33:28 29 4
gpt4 key购买 nike

我有一个第 3 方 C 库,其导出方法之一如下:

#define MAX_INDEX 8
int GetStuff(IN char* index[MAX_INDEX], OUT char* buf, IN size_t size);

第一个参数用指向存储特定字符串的 buf 参数的指针填充。大小表示每个字符串预计在 buf 缓冲区中的长度。我的 C# P/Invoke 方法目前看起来像这样:

[DllImport("Path/To/Dll", CharSet = CharSet.Ansi)]
private static extern int GetStuff(IntPtr indecies, IntPtr buf, Int32 size);

C# P/Invoke 方法是私有(private)的,因为我将它的功能包装在一个公共(public)的“getter”方法中,该方法为调用者处理内存的分配/解除分配。当我在 C++ 中使用此方法时,迭代实际上非常简单。我只是做类似的事情:

char* pIndecies[MAX_INDEX];
char* pBuffer = new char[MAX_INDEX * (256 + 1)]; // +1 for terminating NULL

GetStuff(pIndecies, pBuffer, 256);

// iterate over the items
for(int i(0); i < MAX_INDEX; i++) {
if(pIndecies[i]) {
std::cout << "String for index: " << i << " " << pIndecies[i] << std::endl;
}
}

由于这些在 C++ 中的使用方式,我决定我可能应该使用 IntPtr 对象并仅从堆中分配我需要的内存,调用 native 代码,然后像在 C++ 中那样对其进行迭代.然后我想起了 C# 中的字符是 unicode 字符而不是 ASCII 字符。即使我将迭代放在不安全的代码块中,C# 中的迭代是否也能正常工作?我的第一个想法是执行以下操作:

IntPtr pIndecies = Marshal.AllocHGlobal(MAX_INDEX * 4); // the size of a 32-pointer
IntPtr pBuffer = Marshal.AllocHGlobal(MAX_INDEX * (256 + 1)); // should be the same
NativeMethods.GetStuff(pIndecies, pBuffer, 256);

unsafe {
char* pCStrings = (char*)pIndecies.ToPointer();
for(int i = 0; i < MAX_INDEX; i++) {
if(pCStrings[i])
string s = pCStrings[i];
}
}

然后我的问题是,“我应该如何迭代这个 native 代码方法返回的内容?”这是编码此功能的正确方法吗?我应该为第二个参数使用 StringBuilder 对象吗?一个限制性问题是第一个参数是 GetStuff() 方法后面的结构的 1:1 映射。每个索引的值对于理解您在第二个缓冲区参数中查看的内容至关重要。

我很感激任何建议。

谢谢,安迪

最佳答案

我认为您走在正确的轨道上,但我会在不使用不安全代码的情况下做到这一点。像这样:

[DllImport("Path/To/Dll", CharSet = CharSet.Ansi)]
private static extern int GetStuff(IntPtr[] index, IntPtr buf, Int32 size);
....
IntPtr[] index = new IntPtr[MAX_INDEX];
IntPtr pBuffer = Marshal.AllocHGlobal(MAX_INDEX * 256 + 1);
try
{
int res = NativeMethods.GetStuff(index, pBuffer, 256);
// check res for errors?
foreach (IntPtr item in index)
{
if (item != IntPtr.Zero)
string s = Marshal.PtrToStrAnsi(item);
}
}
finally
{
Marshal.FreeHGlobal(pBuffer);
}

这是对您的 C++ 版本的非常直接的翻译。

关于c# - 遍历使用 Marshal.AllocHGlobal() 分配的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9981626/

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