大佬教程收集整理的这篇文章主要介绍了如何将C#List中创建的对象的地址传递给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;
解析一些文本文件后.
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 appropriate GCHandle.Free(handlE);
在做这样的事情时,请记住长时间在内存中固定对象是个坏主意,因为它会阻止垃圾收集器有效地完成其工作.
以上是大佬教程为你收集整理的如何将C#List中创建的对象的地址传递给C dll?全部内容,希望文章能够帮你解决如何将C#List中创建的对象的地址传递给C dll?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。