如何将基于字符**的数组从基于C的dll转换为等价的C#
本文关键字:转换 dll 数组 字符 于字符 | 更新日期: 2023-09-27 18:25:31
如何将C中基于char**
的数组转换为C#中的等效类型?
我有一个DLL,它有一个函数,它使用char**
缓冲区并用正确的数据填充它。
我使用DllImport
在C#应用程序中使用此DLL
当我需要为这些函数指定return type
或argument type
时,问题就开始了。
C#中的哪种类型等效于C char**
数组?
我应该整理什么以及如何整理?
更新:
这是我的C函数,它位于我的dll中:
CDLL_API wchar_t** GetResults(wchar_t* word, int* length, int threshold = 9);
这两个函数调用以下函数来获得它们的值:
wchar_t** xGramManipulator::CGetNextWordsList(const wchar_t* currentWord, int threshold)
{
wstring str(currentWord);
auto result = GetNextWordsList(str, threshold);
return GetCConvertedString(result);
}
wchar_t ** xGramManipulator::GetCConvertedString(vector< wstring> const &input)
{
DisposeBuffers();//deallocates the previously allocated cStringArrayBuffer.
cStringArraybuffer = new wchar_t*[input.size()];
for (int i = 0; i < input.size(); i++)
{
cStringArraybuffer[i] = new wchar_t[input[i].size()+1];
wcscpy_s(cStringArraybuffer[i], input[i].size() + 1, input[i].c_str());
cStringArraySize++;
}
return cStringArraybuffer;
}
我使用了wchar_T**,但我认为C#端应该没有任何区别(因为C#默认支持unicode!所以如果它不同,请也解决这个问题)
在评论中,您表示对处理此函数最感兴趣:
CDLL_API wchar_t** GetResults(wchar_t* word, int threshold);
您不能期望p/invoke marshaller为您封送返回值。你需要手动完成。更重要的是,您无法可靠地调用当前设计的函数。这是因为调用者无法获得返回数组的长度。您需要添加一个额外的参数来将数组长度返回给调用者:
CDLL_API wchar_t** GetResults(wchar_t* word, int threshold, int* len);
在C#方面,你会这样声明:
[DllImport(@"DllName.dll", CallingConvention=CallingConvention.Cdecl)]
static extern IntPtr GetResults(
[MarshalAs(UnmanagedType.LPWStr)]
string word,
int threshold,
out int len
);
您需要确保在DllImport
中指定的调用约定与本机代码的调用约定相匹配。我假设cdecl
,但只有你能确定。
这样称呼它:
int len;
IntPtr results = GetResults(word, threshold, out len);
IntPtr[] ptrs = new IntPtr[len];
Marshal.Copy(results, ptrs, 0, len);
for (int i=0; i<len; i++)
{
string item = Marshal.PtrToStringUni(ptrs[i]);
}
为了避免内存泄漏,您需要导出另一个函数来释放GetResults
分配的内存。呼叫完PtrToStringUni
后再呼叫。
坦率地说,这看起来更适合混合模式的C++/CLI解决方案。