【问题标题】:pass an array of strings from C# to a C++ dll and back again将字符串数组从 C# 传递到 C++ dll 并再次返回
【发布时间】:2013-05-03 02:04:48
【问题描述】:

我查看了 googleverse 和堆栈溢出,并看到了几个类似的问题,但我找到的答案都没有对我有用。我是新成员,所以我不能评论别人问题的答案以要求澄清,所以我不得不求助于自己的问题。

好的,所以我尝试将字符串数组从 C# 应用程序传递到 C++ dll,然后在另一个 C# 应用程序中获取该信息。我相信我正在正确地传递给 C++,但我无法从 dll 中获取正确的字符串。

我像这样传递给 C++:

[DllImport("KinectPlugins.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern void SetGrammarData(string[] strArr, int size);


    public void SetGrammar(string[] strArr)
    {
        SetGrammarData(strArr, strArr.Length);
    }

我的 C++ 代码如下所示:

#define EXPORT_API __declspec(dllexport)
#pragma data_seg(".SHARED")
    char** grammarData;
    int grammarDataLength = 0;
#pragma data_seg()
#pragma comment(linker, "/section:.SHARED,RWS")

EXPORT_API void SetGrammarData(char** strArr, int size)
{
    grammarData = strArr;
    grammarDataLength = size;
}

EXPORT_API int GetGrammarDataLength()
{
    return grammarDataLength;
}
EXPORT_API char** GetGrammarData()
{
    return grammarData;
}

然后在我的其他 C# 应用程序中获取信息的代码如下所示:

[DllImport("KinectPlugins.dll")]
private static extern IntPtr GetGrammarData();
[DllImport("KinectPlugins.dll")]
private static extern int GetGrammarDataLength();

public string[] GetGrammar()
{
    int size = GetGrammarDataLength();
    List<string> list = new List<string>();
    IntPtr ptr = GetGrammarData();
    IntPtr strPtr;
    for (int i = 0; i < size; i++)
    {
        Console.WriteLine("i = " + i);
        strPtr = Marshal.ReadIntPtr(ptr);
        list.Add(Marshal.PtrToStringAnsi(strPtr));
        ptr += Marshal.SizeOf(typeof(IntPtr));
    }
    return list.ToArray();
}

根据我的研究,理论上这应该可行,因为我看到其他几个人使用几乎相同的代码。在实践中,会发生什么是我传入:

SetGrammar(new string[] { "b", "a" });

从另一边回来的是:

stringArray[0] = 
stringArray[1] = H-▬l☺

如果某些人由于某种原因无法查看它或另一个 stringArray[1] 等于 H、-、粗线、l 和笑脸符号。这显然不是我输入的。

有人知道我在哪里可能会出错吗?很长一段时间以来,我一直在努力解决这个问题,并且真的可以使用一些帮助,因为感觉就像我在这里遗漏了一些非常简单的东西。

编辑: 根据 antijon 的建议,我确实更改了我的 SetGrammarData 以复制字符串,但我仍然遇到问题。

新代码:

(inside the data_seg)
wchar_t* grammarData;
(end data_seg)

EXPORT_API void SetGrammarData(wchar_t* strArr, int size)
{
    delete[] grammarData;
    grammarData = new wchar_t[size];
    std::memcpy(grammarData, strArr, sizeof(wchar_t) * size);
    grammarDataLength = size;
}
EXPORT_API wchar_t* GetGrammarData()
{
    return grammarData;
}

现在我得到了这个输出:

stringArray[0] = 8
stringArray[1] = 

C# 代码保持不变。我还缺少什么需要更改的地方吗?

编辑2: 刚刚意识到 wchar_t 就像一个字符,而不是一个字符串,不知道为什么我认为它的行为像一个字符串。回到绘图板上,需要弄清楚如何最好地复制一个 wchar_t**。没有 C++ 经验,但我认为如果不将其传递给我自己就不可能获得 wchar_t* 的长度,但我将不得不对其进行研究。

编辑3: 终于可以正常使用了。

这是我最终得到的结果:

(inside the data_seg)
std::wstring* grammarData;
(end data_seg)

EXPORT_API void SetGrammarData(wchar_t** strArr, int size)
{
    delete[] grammarData;
    grammarDataLength = size;
    grammarData = new std::wstring[size];
    for(int i = 0; i < size; i++)
    {
        grammarData[i] = std::wstring(strArr[i]);
    }
}

EXPORT_API const wchar_t** GetGrammarData()
{
    const wchar_t** wct = new const wchar_t*[grammarDataLength];
    for(int i = 0;i<grammarDataLength;i++)
    {
        const wchar_t* t = grammarData[i].c_str();
        wct[i] = t;
    }
    return wct;
}

编辑4: 以为我让它正常工作,是不正确的。我正在使用传递回自身的 exe 进行测试,但是当通过 dll 传递给另一个 exe 时,什么都不会通过。我现在可以正常工作了:

(inside the data_seg)
wchar_t grammarData[32][50] = {};
(end data_seg)

EXPORT_API void SetGrammarData(wchar_t** strArr, int size)
{
    grammarDataLength = size;
    for(int i = 0; i < size; i++)
    {
        wcscpy(grammarData[i], strArr[i]);
    }
    grammarDataChanged = 1;
}

EXPORT_API wchar_t** GetGrammarData()
{
    wchar_t** wct = new wchar_t*[grammarDataLength];
    for(int i = 0;i<grammarDataLength;i++)
    {
        wct[i] = grammarData[i];
    }

    grammarDataChanged = 0;
    return wct;
}

【问题讨论】:

标签: c# c++ string dll char


【解决方案1】:

这里有几个可能的问题:

  1. 默认情况下,.NET 将封送为wchar_t,而不是char。您需要使用 MarshalAsAttribute 标记您的输入/输出字符串参数才能使用 char。
  2. 如果要保留字符串,则需要在 C 函数中制作它们的副本。在对SetGrammarData 的函数调用中提供给您的指针不能保证持续存在。

【讨论】:

  • 嗯,我什至没有考虑过#2。我想这表明我已经在这个问题上工作了太久并且有太多的迭代以至于忘记了类似的东西。我会尝试解决这个问题,因为你可能是正确的,这是我的主要问题。我今天可能没有测试它,因为我很快就要离开了。可能需要等待明天才能接受这个答案。
  • 嗯,我试过了:EXPORT_API void SetGrammarData(wchar_t* strArr, int size) { delete[] grammarData;语法数据 = 新 wchar_t[大小]; std::memcpy(grammarData, strArr, sizeof(wchar_t) * size);语法数据长度 = 大小; } EXPORT_API wchar_t* GetGrammarData() { 返回语法数据;但现在我得到的只是: stringArray[0] = 8 stringArray[1] = 你知道我做错了什么吗?
猜你喜欢
  • 2013-10-27
  • 2014-01-12
  • 1970-01-01
  • 2012-02-12
  • 2014-02-24
  • 2010-12-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多