在C#和C之间传递对象

我的应用程序包含带有非托管C dll调用的C#代码。 在我的C#代码中,我有一个对象/类,其属性是系统类型,如string和int以及我定义的其他对象。

我想将这个复杂的(Graph.cs)对象传递给我的C(dll)代码,你会在这里建议什么实现?

我已经尝试过移动结构但是我没有使用除了string和int之外的任何东西。

谢谢。

码:

public Class Grpah { TupleCollection m_TupleCollection; int m_nGeneralIndex; bool m_bPrintWRF; string m_sLink; } public Class TupleCollection { IList _collection; } public Class Tuple { Globals.TupleType m_ToppleType; ArrayList m_Parameters; } public class TupleArgs { public string Value { get; set; } public Globals.PAS PAS; public RefCollection RefCollection { get; set; } public int Time{ get; set; } } public class RefCollection { public List SynSet{ get; set; } public Globals.PAS PAS; } 

尝试:

如何:使用PInvoke的Marshal结构

我认为最简单的方法是修改本机代码,使其能够使用CLR类型。

现在,你几乎肯定会使用Visual Studio,希望它是VS2005或更高版本。 这意味着虽然您现有的本机代码在C中,但您可以选择深入研究一点C ++。 不仅如此 – 您还拥有C ++ / CLI。

所以我会创建一个新的C ++ / CLI DLL,并将你的C库链接到它,以便它可以调用C代码。 然后在C ++ / CLI库中编写一个精简的转换层:它将公开真正的CLR类(用ref class编写)并将调用本机C代码。

例如在C标题中:

 void do_something_with_foo_data(int a, int b, int c); 

在C ++ / CLI中:

 public ref class FooWrapper { static void DoSomethingWithFoo(Foo ^foo) { // pick apart the Foo class and pass the pieces on to the C function do_something_with_foo_data(foo->A, foo->B, foo->C); } }; 

在C#中:

 public class Foo { public int A { get; set; } public int B { get; set; } public int C { get; set; } } ... var foo = new Foo { A = 1, B = 2, C = 3 }; FooWrapper.DoSomethingWithFoo(foo); 

当我这样做时,我只使用了Marshal 。 这与本机代码的标准C相同。 我不想将我的C代码转换为“托管C ++”或他们称之为的任何东西:-)

繁琐而乏味的部分是您必须手动将数据结构编组为直接映射到接收C函数的内容。 在我的情况下,我必须为每个承载C#的数据创建单独的结构 – 我要发送的类。 本质上,您应该将您的C#对象层次结构转换为更基本的forms,然后将结构组织成一个内存块, 然后将其用作本机调用中的参数。

您应该使用Marshal.AllocHGlobal方法分配内存,使用Marshal.StructureToPtr将C#结构复制到该内存,然后使用Marshal.FreeHGlobal释放它。

一旦你有了IntPtr(来自StructureToPtr ),你应该能够简单地用你的指针作为参数来调用你的C-dll。 请注意,要发送到C函数的结构必须与本机C结构具有相同的布局,否则您将获得非常奇怪的结果。

返回数据几乎是一回事,但您正在使用相反的函数( PtrToStructure等)。

无论如何,这是它的基础。

你的模型看起来很复杂,不完整:Tuple.m_parameters是一个ArrayList,所以它几乎可以包含任何东西,并且这里没有定义Globals.PAS类型。

也许您应该考虑一个不同的策略:在您的DLL中,创建一个包含C代码中所需内容的小模型,并使其尽可能简单(但不是更简单!)。

然后,学习从托管代码编组C模型所需的任何内容,并从Graph.cs类中填写模型。 最好,Graph.cs不应该对此负责,您的编组代码应该是。