如何将结构从非托管C ++程序传递给C#程序?

时间:2009-08-08 23:23:12

标签: c# c++ interop struct

这是我的第二篇文章。

以下是我要做的事情:从c#调用非托管c ++程序,从c#程序传入一个结构数组,并从c ++程序返回结构数组的更新版本。

这是调用c#程序:

using System;
using System.Runtime.InteropServices;

namespace TestCallingC
{
    class Program
    {
        [DllImport(@"..\..\..\Debug\TestCProgram.dll")]
        public static extern void testfunc(teststruc[] ts);

        static void Main(string[] args)
        {
            teststruc[] teststructs = new teststruc[6];
            for (int i = 0; i < teststructs.Length; i++)
            {
                teststructs[i].int1 = (i + 1) * 100;
                teststructs[i].int2 = (i + 1) * 100;
            }

            testfunc(teststructs);
            for (int i = 0; i < teststructs.Length; i++)
            {
                Console.WriteLine("Int1 = {0}", teststructs[i].int1);
                Console.WriteLine("Int2 = {0}", teststructs[i].int2);
            }
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct teststruc
    {
        [MarshalAs(UnmanagedType.I4)]
        public int int1;
        [MarshalAs(UnmanagedType.I4)]
        public int int2;
    }
}

这是返回的c ++程序:

extern "C" __declspec(dllexport) void testfunc (teststruc* ts)
{
    int i;

    for (i = 0; i < 6; i++)
    {

        ts[i].int1 = i;
        ts[i].int2 = i;
    }

    for (i = 0; i < 6; i++)
    {
        printf("ts[%d].int1 = %d\n", i, ts[i].int1);
        printf("ts[%d].int2 = %d\n", i, ts[i].int2);
    }

    return;
}

我上面提到的版本允许c ++程序查看并打印出从c#程序传递的入站结构。当控件传递回c#程序时,数据与最初设置的数据相同。它允许通过被调用的c ++程序更新结构。这是控制台输出。第一部分显示了来自teh的更新字段,称为c ++程序;第二部分是c#最初设置的内容 呼叫者:

ts[0].int1 = 0
ts[0].int2 = 0
ts[1].int1 = 1
ts[1].int2 = 1    
ts[2].int1 = 2
ts[2].int2 = 2    
ts[3].int1 = 3
ts[3].int2 = 3    
ts[4].int1 = 4
ts[4].int2 = 4
ts[5].int1 = 5
ts[5].int2 = 5

Int1 = 100
Int2 = 100
Int1 = 200
Int2 = 200
Int1 = 300
Int2 = 300
Int1 = 400
Int2 = 400
Int1 = 500
Int2 = 500
Int1 = 600
Int2 = 600

如果我将“ref”标记添加到c#调用签名中,则从c ++程序返回的结构为null:

[DllImport(@"..\..\..\Debug\TestCProgram.dll")]
        public static extern void testfunc(ref teststruc[] ts);

testfunc(ref teststructs);

问题:需要对c ++和c#程序中的接口进行哪些更新才能在c ++程序中正确更新结构并返回到c#程序?

我发现了很多关于类似事情的信息,但没有任何东西给我正确的组合来实现它。欢迎任何建议。

谢谢。 -Greg

2 个答案:

答案 0 :(得分:1)

随机猜测:

[DllImport(@"..\..\..\Debug\TestCProgram.dll")]
public static extern void testfunc([In, Out] teststruc[] ts);

来自MSDN

  

组合InAttributeOutAttribute在应用于数组和格式化的非blittable类型时特别有用。调用者只有在应用这两个属性时才会看到被调用者对这些类型所做的更改。 [...]

答案 1 :(得分:0)

最终解决方案:

C ++(初始版本没有变化)。

C#代码:

using System;
using System.Runtime.InteropServices;

namespace TestCallingC
{
    class Program
    {
        [DllImport(@"..\..\..\Debug\TestCProgram.dll")]
        public static extern void testfunc([In, Out] teststruc[] ts);

        static void Main(string[] args)
        {
            teststruc[] teststructs = new teststruc[6];
            for (int i = 0; i < teststructs.Length; i++)
            {
                teststructs[i].int1 = (i + 1) * 100;
                teststructs[i].int2 = (i + 1) * 100;
            }

            testfunc(teststructs);
            for (int i = 0; i < teststructs.Length; i++)
            {
                Console.WriteLine("Int1 = {0}", teststructs[i].int1);
                Console.WriteLine("Int2 = {0}", teststructs[i].int2);
            }
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct teststruc
    {
        [MarshalAs(UnmanagedType.I4)]
        public int int1;
        [MarshalAs(UnmanagedType.I4)]
        public int int2;
    }
}