从C++传递字符串数组到C#

8

我已经写了这段代码,它运行得很好:
C++ 代码

extern "C"
{
    const MYLIBRARY_EXPORT char* giefStrPlx(char* addon)
    {
        return addon;
    }
}

C# 代码

[DllImport("ClassLibrary1")]
private static extern IntPtr giefStrPlx(string x);

void Start()
{

    IntPtr stringPtr = giefStrPlx("Huntsman");
    string huntsman = Marshal.PtrToStringAnsi(echoedStringPtr);
}

在这之后,huntsman 就包含了 "Huntsman"。


我的问题是对一个字符串数组执行类似操作的步骤。我编写了以下函数:

extern "C"
{
    const MYLIBRARY_EXPORT bool fillStrArray(char** lizt, int* length)
    {
        char* one = "one";
        char* two = "two";
        char* three = "three";

        lizt[0] = one;
        lizt[1] = two;
        lizt[2] = three;

        *length = 3;
    }
}

我尝试用C#编写了以下代码:

[DllImport("ClassLibrary1")]
private static extern bool fillStrArray(ref IntPtr array, ref int length);

void Start()
{
    IntPtr charArray = IntPtr.Zero;
    int charArraySize = 0;
    fillStrArray(ref charArray, ref charArraySize);

    IntPtr[] results = new IntPtr[charArraySize];
    Marshal.Copy(charArray, results, 0, charArraySize);

    foreach (IntPtr ptr in results)
    {
        string str = Marshal.PtrToStringAnsi(ptr);
    }
}

这并不起作用。所以现在我有点不知道该如何完成此操作。


你的C代码要求传递一个指向内存的指针,以便它可以将字符串指针写入其中。IntPtr.Zero不可写。您也不知道需要分配多少内存。使用IntPtr charArray = Marshal.AllocHGlobal(crossMyFingers) ,其中crossMyFingers是一个大数字,对于此代码至少应为3 * IntPtr.Size,但应更大以减少堆破坏的可能性。您可以设置length参数来帮助避免这种类型的破坏。 - Hans Passant
谢谢指点。即使进行了更改,我仍然遇到问题。我正在尝试在Unity中使用它,但插件会使其崩溃,这使得调试更加困难。我没有传递一个数组指针,而是返回了一个指针,与我在第一个示例中所做的类似。 - Bjorninn
1个回答

1

这里有两个辅助函数,一个是从CLR到std::string的转换,另一个是从std::string到CLR的转换。

std::string CLROperations::ClrStringToStdString(String^ str)
{
    if (String::IsNullOrEmpty(str))
        return "";

    std::string outStr;
    IntPtr ansiStr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str); 
    outStr = (const char*)ansiStr.ToPointer(); 
    System::Runtime::InteropServices::Marshal::FreeHGlobal(ansiStr); 
    return outStr;
}

String ^ CLROperations::StdStringToClr(std::string str)
{
    return gcnew String(str.c_str());
}

如果要使用字符串列表,您需要使用 List<String^>^,注意 String 的大写。如果要使用 std::string 的列表,请使用 std::vector<std::string>


很抱歉,但我不明白这怎样能帮助我解决我的问题。 - Bjorninn
不要使用 IntPtr 和 char*,请改用 std::string。 - Gilad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接