将字符串数组从C#传递到C ++ dll,然后再次返回 [英] pass an array of strings from C# to a C++ dll and back again

查看:65
本文介绍了将字符串数组从C#传递到C ++ dll,然后再次返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我环顾了googleverse和堆栈溢出,并看到了与此类似的几个问题,但是我发现的答案都没有为我解决.我是新成员,因此我不允许评论别人的问题以要求澄清,所以我不得不求助于我自己的问题.

I have looked around the googleverse and stack overflow and have seen several similar questions to this but none of the answers I have found have worked for me. I am a new member so I am not allowed to comment on answers in someone else's question to ask for clarification so I have had to resort to asking my own.

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

Ok so I am trying to pass a string array from a C# application to a C++ dll and then grab that information in another C# application. I believe I am passing to C++ properly but I can't get proper strings back from the dll.

我像这样传递给C ++:

I am passing to C++ like so:

[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 ++代码如下:

My C++ code looks like this:

#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#应用程序中获取信息的代码如下:

My code for then grabbing the information in my other C# application looks like this:

[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();
}

理论上,这应该基于我的研究,因为我已经看到其他几个人使用几乎相同的代码.在实践中,发生的事情是我通过了:

In theory this should work based on my research as I have seen several other people use almost the same code. In practice, what happens is I pass in:

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

另一面又是:

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

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

In case some can't view it for some reason or another stringArray[1] is equal to H, -, a thick line, l and a happy face symbol. This is obviously not what I put in.

有人知道我可能在哪里出错吗?我花了很长时间来解决这个问题,并且真的可以使用一些帮助,因为感觉好像我在这里错过了一些非常简单的事情.

Does anyone have an idea where I could be going wrong with this? I have been banging my head against this problem for quite a while and could really use some help as it feels like I am missing something really simple here.

修改:根据antijon的建议,我确实更改了SetGrammarData来复制字符串,但仍然遇到问题.

as per antijon's suggestion I did change my SetGrammarData to make a copy of the strings but I am still running into an issue.

新代码:

(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#代码保持不变.我还有其他需要改变的东西吗?

The C# code has remained the same. Is there something else I need to change that I am missing?

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

Just realized that wchar_t is like a char, not a string, not sure why I thought it behaved like a string. Back to the drawing board, need to figure out how to best copy a wchar_t**. Not that experienced with C++ but I don't think it's possible to get the length of a wchar_t* without passing it in myself but I will have to look into it.

Edit3:终于让它正常工作了.

Finally got it working properly.

这就是我最后得到的:

(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;
}

以为我可以正常工作,这是不正确的.我正在测试一个传回自己的exe文件,但是当通过dll传递到另一个exe文件时,什么也不会通过.现在,我可以使用它了:

Thought I had it working properly, was incorrect. I was testing with an exe passing back to itself but when passing through the dll to another exe nothing would come through. I now have it working:

(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;
}

推荐答案

这里可能存在的问题:

  1. 默认情况下,.NET将封送为 wchar_t ,而不是 char .您需要使用 MarshalAsAttribute 标记输入/输出字符串参数才能使用字符.
  2. 如果要保留字符串,则需要在C函数中复制它们.在函数调用 SetGrammarData 中给您的指针不能保证持久存在.
  1. By default, .NET will marshal as wchar_t, not char. You will need to mark your input/output string parameters with MarshalAsAttribute to use char.
  2. If you want to keep the strings, you will need to make copies of them within the C function. The pointers given to you in the function call to SetGrammarData are not guaranteed to persist.

这篇关于将字符串数组从C#传递到C ++ dll,然后再次返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆