简体   繁体   English

非托管导出,将字符串数组从C ++传递到C#

[英]Unmanaged Exports, passing an array of strings from C++ to C#

I'm using Robert Giesecke's Unmanaged Exports package to be able to call from C++ to C#. 我正在使用Robert Giesecke的Unmanaged Exports包来调用C ++到C#。 This has to use the C interface from within C++. 这必须使用C ++中的C接口。 I have managed to get most things working, by scouring the web and picking up bits here and there.... 我已经成功地通过搜索网络并在这里和那里拾取了大部分工作....

extern "C"
{
    //  Simple
    __declspec(dllimport) int IntTest(int input);
    __declspec(dllimport) double DoubleTest(double input);

    //  Array of simple types in
    __declspec(dllimport) int passArray(int t[], int i, int xx);

    //  String in and out
    __declspec(dllimport) int PassStringIn(wchar_t* str);
    __declspec(dllimport) int PassStringOut(wchar_t** str);
    __declspec(dllimport) wchar_t* PassStringInOut(wchar_t* str);

    //  Array of strings types in
    //__declspec(dllimport) int passArrayStrings(char** t, int i);
}

.... ....

//  Int in and out
int aa = IntTest(4);

//  Double in and out
double bb = DoubleTest(4.3);

//  Pass array in
int arr[4] = { 1,2,3,4 };
int cc = passArray(arr, 4, 0);

//  String in
wchar_t* a_str = L"input string from C++";
int dd = PassStringIn(a_str);

//  String out
wchar_t* b_str = L"not used";
int ee = PassStringOut(&b_str);

//  String in & out
wchar_t* d_str = L"bob";
wchar_t* result = PassStringInOut(d_str);

corresponding C# 对应的C#

    [DllExport( CallingConvention = CallingConvention.Cdecl)]
    static int IntTest(int input)
    {
        return input + 1;
    }

    [DllExport(CallingConvention = CallingConvention.Cdecl)]
    static double DoubleTest(double input)
    {
        return input + 1;
    }

    [DllExport(CallingConvention = CallingConvention.Cdecl)]
    public static int passArray([In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]  int[] tab, int i, int x)
    {
        return tab[x];
    }

    [DllExport(CallingConvention = CallingConvention.Cdecl)]
    public static int PassStringIn( [MarshalAs(UnmanagedType.LPWStr)] string inputString)
    {
        Console.WriteLine("Hi, the string passed in was :" + inputString);
        return 1;
    }

    [DllExport(CallingConvention = CallingConvention.Cdecl)]
    static int PassStringOut([MarshalAs(UnmanagedType.BStr)] out string outputString)
    {
        Console.WriteLine("Hi, I will return the time from c#");
        outputString = DateTime.Now.ToLongTimeString();
        return 0; // indicates success
    }

    [DllExport(CallingConvention = CallingConvention.Cdecl)]
    [return: MarshalAs(UnmanagedType.LPTStr)]
    public static string PassStringInOut([MarshalAs(UnmanagedType.LPTStr)]string name)
    {
        return string.Format("Hello from .NET assembly, {0}!", name);
    }

Which was nice! 哪个好! Anyway would anybody be able to help with passing arrays of strings in and out. 无论如何,任何人都可以帮助传入和传出字符串数组。 I am pretty sure the C# section should look like this: 我很确定C#部分应该如下所示:

    [DllExport(CallingConvention = CallingConvention.Cdecl)]
    public static int passArrayStrings( [In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 1)]  string[] tab, int i)
    {

        return 1;
    }

I need some help on the C++(C) side on how to structure the array of strings in, such that they can be marshaled correctly. 我需要在C ++(C)方面提供一些关于如何构造字符串数组的帮助,以便它们可以正确编组。 The mixed mode assembly created has both C# and and a C interface. 创建的混合模式程序集同时具有C#和C接口。 As it is C and not C++ the arguments types of the exposed functions are not visible. 因为它是C而不是C ++,所以暴露函数的参数类型是不可见的。

依赖沃克

Thanks 谢谢

You can use an IntPtr parameter. 您可以使用IntPtr参数。

You'll have to allocate unmanaged memory and copy the array into that blob anyway. 你必须分配非托管内存并将数组复制到该blob中。 Otherwise the GC will eat your array at some point. 否则GC会在某个时刻吃掉你的阵列。

Unmanaged Exports with Arrays 使用数组的非托管导出

ok so after a lot of messing about I came to a solution: 好吧,经过大量的混乱,我找到了解决方案:

//  Array of strings types in
__declspec(dllimport) int passArrayStrings(BSTR* bstrArray, int i);

BSTR bstrArray[10] = { 0 };
for (int i = 0; i < 10; i++)
{
    bstrArray[i] = ::SysAllocString(L"My String.");
}
int ff = passArrayStrings(bstrArray, 10);
for (int i = 0; i < 10; i++)
{
    ::SysFreeString(bstrArray[i]);
}

and on the c# side: 在c#方面:

    [DllExport(CallingConvention = CallingConvention.Cdecl)]
    public static int passArrayStrings([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.BStr, SizeParamIndex = 1)]  string[] tab, int iSize)
    {
        return 1;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM