如何将基于字符**的数组从基于C的dll转换为等价的C#

本文关键字:转换 dll 数组 字符 于字符 | 更新日期: 2023-09-27 18:25:31

如何将C中基于char**的数组转换为C#中的等效类型?

我有一个DLL,它有一个函数,它使用char**缓冲区并用正确的数据填充它。

我使用DllImport 在C#应用程序中使用此DLL

当我需要为这些函数指定return typeargument 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!所以如果它不同,请也解决这个问题)

如何将基于字符**的数组从基于C的dll转换为等价的C#

在评论中,您表示对处理此函数最感兴趣:

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解决方案。