从C#lib返回一个包含字符串的结构到C ++程序

时间:2019-05-04 11:19:36

标签: c# c++ interop

我正在尝试从C ++程序调用C#库。 C#和这个互操作对我来说是很新的。在我不得不面对结构内部的字符串之前,某些沟通很容易。我已经阅读了很多,看到了几个示例,但是我无法复制它们并使它们正常工作。

我以发送字符串并检索有效的字符串为例提取了代码(_string_exchange)。和_return_struct方法,它返回一个带有无效字符串的结构。当我尝试将变量用于std :: cout时,调试器失败,但未处理的异常来自0x00007FFFEA98A388(KernelBase.dll)。通话期间Console.WriteLine尚未编写任何内容。

我认为这是与脚本匹配的问题。两者均使用.NET Framework 4.6.1在x64版中进行编译。我也一直在检查sizeof()和Marshal.SizeOf()来检查它们是否具有相同的字节长度。还尝试将c ++项目字符从unicode更改为多字节,但没有成功。

我看到类似这样的示例可以很好地解释所有内容,但是我不知道自己缺少什么:Passing strings/arrays within structures between C++/C#

C ++程序:

struct myStruct
{
    int myInt;
    double myDouble;
    bool myBool;
    char myString[64];
}; 

int main() {
    const TCHAR* pemodule = _T("F:\\PATH\\TO\\DLLsi\\LibCSharp.dll");
    HMODULE lib = LoadLibrary(pemodule);

    typedef LPCSTR(_cdecl *_string_exchange)(LPCSTR s);
    auto pString_exchange = (_string_exchange)GetProcAddress(lib, "_string_exchange");
    LPCSTR test = pString_exchange("LPCSTR test works fine");
    std::cout << test << std::endl;

    typedef myStruct(_cdecl *_return_struct)();
    auto pReturn_struct = (_return_struct)GetProcAddress(lib, "_return_struct");
    myStruct aStruct = pReturn_struct();
    std::cout << aStruct.myString << aStruct.myBool << " " << aStruct.myDouble << " " << aStruct.myInt << std::endl;

    return 0;
}

C#库:

namespace LibCSharp
{    
    public class Class1
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct myStruct
        {
            public int myInt;
            public double myDouble;
            [MarshalAs(UnmanagedType.U1)]
            public byte myBool;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public string myString;
        }

        [DllExport]
        public static myStruct _return_struct()
        {
            Console.WriteLine("test");
            myStruct a;
            a.myInt = 3;
            a.myDouble = 2;
            a.myBool = 1;
            Console.WriteLine(a.myBool);
            a.myString = "Hello world! My values are: ";//28
            Console.WriteLine(a.myString);
            return a;
        }

        [DllExport]
        public static string _string_exchange(string s)
        {
            Console.WriteLine(s);
            return s;
        }
    }
}

我也希望将来将这个结构做成一个数组,希望一旦解决就不会遇到很多问题,但是事先提出任何意见也是可以的。

提前谢谢

2 个答案:

答案 0 :(得分:0)

也许您应该尝试使用命名管道在两个进程之间进行通信。它允许您打开流并传输任何字节数组。因此,您可以将任何对象序列化为数组并进行传输。

这里solution用于C ++和C#通信。

与互操作相比,管道更灵活且与系统无关。但效率可能较低...

答案 1 :(得分:0)

乍看之下,您的C#代码似乎在编组,将字符串返回为tchar[64],这几乎可以肯定是Unicode wchar[64];而您的C ++代码则期望使用ascii char[64]

尝试将c ++定义更改为

struct myStruct
{
    int myInt;
    double myDouble;
    bool myBool;
    TCHAR myString[64];
};