我的应用程序包含带有非托管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<Tuple> _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<int> SynSet{ get; set; }
public Globals.PAS PAS;
}
答案 0 :(得分:6)
尝试:
How to: Marshal Structures Using PInvoke
我认为您取得进步的最简单方法是修改本机代码,使其能够使用CLR类型。
现在,您几乎肯定会使用Visual Studio,并且希望它是VS2005或更高版本。这意味着虽然您现有的本机代码在C中,但您可以选择深入研究一点C ++。不仅如此 - 您还拥有C ++ / CLI。
因此,我将创建一个新的C ++ / CLI DLL,并将您的C库链接到它,以便它可以调用C代码。然后在C ++ / CLI库中编写一个精简的转换层:它将公开真正的CLR类(用ref class
编写)并将调用本机C代码。
e.g。在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);
答案 1 :(得分:2)
当我这样做时,我只使用了Marshal。这与本机代码的标准C一致。我不想将我的C代码转换为“托管C ++”或他们称之为: - )
困难和乏味的部分是您必须手动将数据结构编组为直接映射到接收C函数的内容。就我而言,我必须为每个带有C#的数据创建单独的结构 - 我要发送的类。本质上,您应该将您的C#对象层次结构转换为更基本的形式,然后将结构组织成一个内存块,然后然后将其用作本机调用中的参数。
您应该使用方法Marshal.AllocHGlobal
来分配内存,使用Marshal.StructureToPtr
将C#结构复制到该内存,然后使用Marshal.FreeHGlobal
来释放它。
一旦你有了IntPtr(来自StructureToPtr
),你应该能够简单地用你的指针作为参数调用你的C-dll。请注意,要发送到C函数的结构必须与本机C结构具有相同的布局,否则会得到非常奇怪的结果。
返回数据几乎是一回事,但你正在使用相反的函数(PtrToStructure
等)。
无论如何都是它的基础。
答案 2 :(得分:0)
你的模型看起来很复杂,不完整:Tuple.m_parameters是一个ArrayList,所以它几乎可以包含任何内容,而且这里没有定义Globals.PAS类型。
也许您应该考虑一个不同的策略:在您的DLL中,创建一个包含C代码中所需内容的小模型,并使其尽可能简单(但不是更简单!)。
然后,学习从托管代码编组C模型所需的任何内容,并从Graph.cs类中填写模型。最好,Graph.cs不应该对此负责,您的编组代码应该是。