关于C# 调用 C++动态库

本文介绍如何使用C#调用DLL中的函数来获取结构体数组,并提供了具体实现方法和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在写一个C#控制LED显示的程序,LED显示控制那儿,只提供了一个dll;

幸好,还有头文件;

例如,类似于这样的一个接口,

int DCCCALL led3_dcc_get_dtu_list(int dcc_hdl, struct dtu_unit *list, int num);

如果,返回一个列表回填到 list其实的结构内存块中;

如果你不熟悉的话,很有可能写出如下的代码:

[DllImport("led3_dcc.dll")]
public static extern int led3_dcc_get_dtu_list(int dcc_hdl,ref dtu_unit[] list, int num); 然后发现,无论如何都无法调用通过;

如果你熟悉一点的话,

[DllImport("led3_dcc.dll")]
public static extern int led3_dcc_get_dtu_list(int dcc_hdl,IntPtr pt, int num);

然后,调用 如下的方法分配一个内存块;

       /// <summary>
        /// 根据结构数组,产生一个非安全模式的内存块,返回该内存块的头指针;
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tAray"></param>
        /// <returns></returns>
        public IntPtr GetIntPtrFromStruct<T>(T[] tAray)
        {
            T[] result = new T[tAray.Length];
            var structSize = Marshal.SizeOf(typeof(T));
            IntPtr pt = Marshal.AllocHGlobal(tAray.Length * structSize);
            for (var x=0; x<tAray.Length; x++)
            {
                Marshal.StructureToPtr(tAray[x],(IntPtr)((UInt32)pt + x * Marshal.SizeOf(typeof(T))), true);
            }
            return pt;            
        }

       然后再去调用 led3_dcc_get_dtu_list 这个方法,不过这些都比较麻烦;应该有更加简单的方法;

 

再改改接口,  

[DllImport("led3_dcc.dll")]

public static extern int led3_dcc_get_dtu_list(int dcc_hdl,ref dtu_unit firstDtuUnit, int num);


然后, 

dtu_unit[] items = new dtu_unit[count];

var readCount = led3_dcc_get_dtu_list(dccHandle, ref items[0], count); 

就可以了;


记得打开 /unsafe 标签。。。


至于原因,没什么好说的;


附带两个写了出来但最后没有实际用到的方法。。。看哪位兄弟有用吧;


        /// <summary>
        /// 利用 Func调用dll中的方法,获得一个结构的列表回来;
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listCount"></param>
        /// <param name="readSturctListFunc"></param>
        /// <returns></returns>
        public  T[] ReadStructList<T>(int listCount, Func<IntPtr, int> readSturctListFunc)
           where T : struct
        {
            T[] result = new T[listCount];
            var structSize = Marshal.SizeOf(typeof(T));
            IntPtr pt = Marshal.AllocHGlobal(listCount * structSize);


            var readCount = readSturctListFunc(pt);
            for (int j = 0; j < readCount; j++)
            {
                result[j] =
                (T)Marshal.PtrToStructure((IntPtr)((UInt32)pt + j * Marshal.SizeOf(typeof(T)))
                , typeof(T));
            }
            Marshal.Release(pt);
            return result;
        }


        /// <summary>
        /// 根据结构数组,产生一个非安全模式的内存块,返回该内存块的头指针;
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tAray"></param>
        /// <returns></returns>
        public IntPtr GetIntPtrFromStruct<T>(T[] tAray)
        {
            T[] result = new T[tAray.Length];
            var structSize = Marshal.SizeOf(typeof(T));
            IntPtr pt = Marshal.AllocHGlobal(tAray.Length * structSize);
            for (var x=0; x<tAray.Length; x++)
            {
                Marshal.StructureToPtr(tAray[x],(IntPtr)((UInt32)pt + x * Marshal.SizeOf(typeof(T))), true);
            }
            return pt;            
        }


        /// <summary>
        /// 根据结构数组,产生一个非安全模式的内存块,返回该内存块的头指针;
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tAray"></param>
        /// <returns></returns>
        public IntPtr GetStructFromIntPtr<T>(IntPtr pt, int count)
        {
            T[] result = new T[count];
            var structSize = Marshal.SizeOf(typeof(T));
            for (int j = 0; j < count; j++)
            {
                result[j] =
                (T)Marshal.PtrToStructure((IntPtr)((UInt32)pt + j * Marshal.SizeOf(typeof(T)))
                , typeof(T));
            }
            return pt;
        }




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值