如何将C#List中创建的对象的地址传递给C dll?

如何将C#List中创建的对象的地址传递给C dll?,第1张

概述我一直在寻找谷歌找到我的问题的一些答案,但不太明白我发现了什么.在使用System.IO读取一些文本文件后,我有一些在C#List中创建和存储的对象.之后,我想将引用(使用const指针)发送到每个这些对象到C dll中的内部类,以便它可以使用它们来计算某些算法. 以下是我正在做的一些简单示例(不是实际代码): C#类: [StructLayout(LayoutKind.Sequential, C 我一直在寻找谷歌找到我的问题的一些答案,但不太明白我发现了什么.在使用System.IO读取一些文本文件后,我有一些在C#List中创建和存储的对象.之后,我想将引用(使用const指针)发送到每个这些对象到C dll中的内部类,以便它可以使用它们来计算某些算法.

以下是我正在做的一些简单示例(不是实际代码):

C#类:

[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi)]public class SimpleClass{    [MarshalAs(UnmanagedType.LPStr)]    public string           name;    public float            Length;}

与相应的C结构:

struct SimpleClass{    const char* name;    float Length;};

存储在

List<SimpleClass> ItemList;

解析一些文本文件后.

然后调用以下dll函数:

C#:

[Dllimport("SimpleDLL")]public static extern voID AddSimpleReference(SimpleClass inSimple);

C:

voID AddSimpleReference(const SimpleClass* inSimple){   g_Vector.push_back(inSimple); // g_Vector is a std::vector<const SimpleClass* > type}

我试过的是:

for(int i=0; i<ItemList.Count;++i){    SimpleClass theSimpleItem = ItemList[i];    AddSimpleReference(theSimpleItem);}

最初,我认为只使用赋值运算符就可以很容易地获得实际的引用/地址,因为C#中的类是通过引用传递的,但事实证明C类总是推送相同的地址值(地址值)临时引用)进入容器而不是实际地址.如何获取实际的对象地址并将其发送到C DLL,以便它可以只读访问C#对象?

更新:对于那些使用不安全代码发布答案的人抱歉.我忘了提到C#代码实际上是用作Unity游戏引擎中的一个脚本,它不允许使用不安全的代码.

解决方法 首先,您需要更改互 *** 作签名以获取指针(从而使其不安全).

[Dllimport("SimpleDLL")]public unsafe static extern voID AddSimpleReference(SimpleClass* inSimple);

然后,因为GC可以随心所欲地在内存中移动对象,所以您需要将对象固定在内存中,以便在非托管端需要其地址的整个时间.为此你需要固定的声明:

SimpleClass theSimpleItem = ItemList[i];unsafe{    fixed(SimpleClass* ptr = &theSimpleItem)    {        AddSimpleReference(ptr);    }}

如果AddSimpleReference使用指针然后丢弃它,这将起作用.但是你将指针存储在std :: vector中以供日后使用.这将无法工作,因为一旦执行离开固定块,GC会将原始项目移动到其他位置,因此指针可能会变得无效.

要解决此问题,您需要固定项目,直到完成它们为止.为此,您可能需要使用GCHandle类型.

// Change the interop signature,use IntPtr instead (no "unsafe" modifIEr)[Dllimport("SimpleDLL")]public static extern voID AddSimpleReference(IntPtr inSimple);// ----for(int i=0; i<ItemList.Count;++i){    SimpleClass theSimpleItem = ItemList[i];    // take a pinned handle before passing the item down.    GCHandle handle = GCHandle.Alloc(theSimpleItem,GCHandleType.Pinned);    AddSimpleReference(GCHandle.ToIntPtr(handle));    // probably a good IDea save this handle somewhere for later release}// ----// when you're done,don't forget to ensure the handle is freed// probably in a dispose method,or a finally block somewhere appropriateGCHandle.Free(handle);

在做这样的事情时,请记住长时间在内存中固定对象是个坏主意,因为它会阻止垃圾收集器有效地完成其工作.

总结

以上是内存溢出为你收集整理的如何将C#List中创建的对象的地址传递给C dll?全部内容,希望文章能够帮你解决如何将C#List中创建的对象的地址传递给C dll?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1213732.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存