在实际工作中,我们经常会将C语言中的.lib和.h文件(静态库)编译成动态连接库.dll文件(这里只提供这两种文件,没有完整的工程),以提供给其他语言平台调用。1,必须有.lib文件,只有.h文件是无法编译动态连接库的。2,我使用的是VS2008,这里打开VS,新建项目—〉win32控制台应用程序,输入项目名称,点击确定,图示如fig.1所示。Fig.13,点击下一步,依次如图fig.2-3所示,最后点击完成,就会生成一个带有.cpp的文件。Fig.2Fig.34,打开项目—属性—配置属性—链接器—输入,如下图fig.4所示,在附加依赖项中加入你要添加的.lib文件,如果有一些系统.lib库没有添加或出现错误,可以在忽略特定库中添加该库。注意:如果编译的dll文件调用中出现“xx.dll中找不到函数xx的入口点”,很有可能是一个xx.def文件没有添加,该文件的内容是EXPORTS函数名@+序号。如果这个文件中没有你要调用的API函数,那么你在C#中是调用不到这个函数的,同时这个文件你可以同坐记事本自己编辑,注意!!!Fig.45,在.cpp文件中添加.h文件的引用,不需要把所有的.h文件都引用进去,只需要.lib文件入口相关的.h文件。6,最后把.lib和.h文件拷贝到工程debug目录里,生成解决方案就Ok了,你会发现.dll在debug目录中出现。第二篇C#调用C/C++的动态连接库
1,清楚C++与C#类型对应关系,即调用关系:C基本类型对照关系----VS2008:除此之外,c++:HANDLE(void*)----c#:System.IntPtrc++:WORD(unsignedshort)----c#:System.UInt16c++:DWORD(unsignedlong)----c#:System.UInt32c++:结构体----c#:publicstruct结构体{};c++:结构体&变量名----c#:ref结构体变量名c++:结构体**变量名----c#:outc++:GUID----c#:Guidc++:UINT8*----c#:refbytec++:char*/void*(指向一个字符串)----c#:string对于结构体中的指针数组,对应于C#中的IntPtr[]类型,如:int*a[]--------------IntPtr[]a2,清楚在C#中调用C/C++.dll文件的一般格式usingSystem.Runtime.InteropServices;//必须引用的命名空间[DllImport(\"user32.dll\")]publicstaticexternReturnTypeFunctionName(typearg1,typearg2,...);//必须定义为类的静态外部的方法3,[DllImport(参数)]设定①“xx.dll”:dll文件名字②CharSet:控制调用函数的名称版本及指示如何向方法封送String参数。如果CharSet字段设置为Unicode,则所有字符串参数在传递到非托管实现之前都转换成Unicode字符。这还导致向DLLEntryPoint的名称中追加字母“W”。如果此字段设置为Ansi,则字符串将转换成ANSI字符串,同时向DLLEntryPoint的名称中追加字母“A”。EntryPoint指示要调用的DLL入口点的名称或序号。如果你想使用自己定义的函数名字fucXX,则:”EntryPoint=fucXX”。③ExactSpelling:指示是否应修改非托管DLL中的入口点的名称,以与CharSet字段中指定的CharSet值相对应。如果为true,则当DllImportAttribute.CharSet字段设置为CharSet的Ansi值时,向方法名称中追加字母A,当DllImportAttribute.CharSet字段设置为CharSet的Unicode值时,向方法的名称中追加字母W。此字段的默认值是false。④PreserveSig:指示托管方法签名不应转换成返回HRESULT、并且可能有一个对应于返回值的附加[out,retval]参数的非托管签名。⑤SetLastError:指示被调用方在从属性化方法返回之前将调用Win32APISetLastError。true指示调用方将调用SetLastError,默认为false。4,具体实例C中API函数:UnsignedlongintFuc(inta,void*b);C#中定义:[DllImport(\"testall.dll\",ExactSpelling=false)]publicexternstaticUInt32Fuc(inta,IntPtrb);//C中结构体:#defineM3typedefstruct__tag_MBITMAP{DWorddwPixelArrayFormat;LonglWidth;LonglHeight;LonglPitch[MPAF_MAX_PLANES];Byte*pPlane[MPAF_MAX_PLANES];}BITMAPC#定义:[StructLayout(LayoutKind.Sequential)]//此句在C#中重新定义结构体时一定要加上publicstructBITMAP{[MarshalAs(UnmanagedType.U4)]publicUInt32dwPixelArrayFormat;[MarshalAs(UnmanagedType.I4)]publicInt32lWidth;[MarshalAs(UnmanagedType.I4)]publicInt32lHeight;[MarshalAs(UnmanagedType.ByValArray,SizeConst=3)]publicInt32[]lPitch;[MarshalAs(UnmanagedType.ByValArray,SizeConst=3)]publicIntPtr[]pPlane;}对于上面的这个结构体,如果在C/C++中出现了结构体指针,那么我们应该在C#中使用IntPtr类型变量,然后使用如下方法将指针指向结构体。定义结构体对象S,则在C#中获取结构体指针的方法如下:IntPtrintptr=Marshal.AllocHGlobal(Marshal.SizeOf(S));Marshal.StructureToPtr(S,intptr,false);//将指针intptr指向结构体操作之后一定要释放内存——Marshal.FreeHGlobal(intptr);//释放分配的非托管内存。反之也可以由指向结构体的指针变量获取结构体。Marshal.PtrToStructure();//对于结构体中的指针数组,一般采用IntPtr数组
因篇幅问题不能全部显示,请点此查看更多更全内容
怀疑对方AI换脸可以让对方摁鼻子 真人摁下去鼻子会变形
女子野生动物园下车狼悄悄靠近 后车司机按喇叭提醒
睡前玩8分钟手机身体兴奋1小时 还可能让你“变丑”
惊蛰为啥吃梨?倒春寒来不来就看惊蛰
男子高速犯困开智能驾驶出事故 60万刚买的奔驰严重损毁