c# 调用c++DLL方法及注意事项
2014-09-26 18:30
344 查看
引用命名空间 using System.Runtime.InteropServices
调用方法:
一、静态加载
用DllImprot方式来加载c++DLL。如下格式:
注意:
1、如果只有一个DLL可以用这种方式,把DLL放在bin/Debug或bin文件夹下,在控制台窗体应用程序和Web网页应用程序都有效。如果有多个DLL,存在依赖调用,如A、B两个DLL,A会调用B里面的方法,因为[DllImport("A.dll")] 这样写只能调用一个DLL,在控制台窗体应用程序中,会自动加载B,但是在Web网页应用程序不会自动加载B,导致返回错误码找不到文件。要是这样写[DllImport("A.dll")] 、[DllImport("B.dll")] ,还是不会加载B。用下面二中的动态加载,依然只能加载一个DLL。解决方法:把A、B复制到系统文件夹下,32位系统复制到c/windows/system32下,64位系统复制到c/windows/syswow64文件夹下,写的时候只用[DllImport("A.dll")],就会自动加载B。这种方式只适用于你可以控制电脑,如果用的别人的服务器空间,没法复制,有可能的话最好把A、B编译到一个DLL中来调用。
2、数据格式对应问题。
二、动态加载
1、用Assembly方式加载,这种方式只适用于托管代码。c++也可以编译为托管代码。依然只能加载一个DLL。
2、用LoadLibrary和GetProcAddress方式加载,这种方式可以加载非托管代码。依然只能加载一个DLL。
如下格式:
三、其他方式
在搜索过程中有些关键字也有启示,但没有往下找。如更改Dll搜索目录,加入bin目录到DLL搜索顺序,DllImport加载依赖项Dll。
四、其他文章,看看
http://www.cnblogs.com/szytwo/archive/2011/12/11/2283780.html http://www.cnblogs.com/kvspas/archive/2008/12/15/1355033.html
如有地方不正确,欢迎提出。
调用方法:
一、静态加载
用DllImprot方式来加载c++DLL。如下格式:
//对应c++方法 //void DogInit(WORD*,HWND) //错误返回值,窗口句柄 [DllImport("DOG.dll", EntryPoint = "DogInit", CallingConvention = CallingConvention.Cdecl)] public static extern void DogInit(out short x, IntPtr hwnd); //对应c++方法 //void DogReadInfo(WORD*,int,unsigned char*,unsigned short) //错误返回值,读取哪项,返回的内容,初始化长度 [DllImport("DOG.dll", EntryPoint = "DogReadInfo", CallingConvention = CallingConvention.Cdecl)] public static extern void DogReadInfo(out short x, int y,[MarshalAs(UnmanagedType.LPArray,SizeConst=512)]byte[] z,short w); /// <summary> /// 初始化加密狗 /// </summary> public static void DogInit() { IntPtr zero = IntPtr.Zero; short x = -1; DogInit(out x,zero); //此时x保存了返回的错误码,如0、1、2 } public static void DogReadInfo() { short x; int y = 0; byte[] z = new byte[512]; short w = 512; DogReadInfo(out x,y,z,w); //此时x保存了返回的错误码 //z保存了返回的读取内容 string content = System.Text.Encoding.Default.GetString(z); }
注意:
1、如果只有一个DLL可以用这种方式,把DLL放在bin/Debug或bin文件夹下,在控制台窗体应用程序和Web网页应用程序都有效。如果有多个DLL,存在依赖调用,如A、B两个DLL,A会调用B里面的方法,因为[DllImport("A.dll")] 这样写只能调用一个DLL,在控制台窗体应用程序中,会自动加载B,但是在Web网页应用程序不会自动加载B,导致返回错误码找不到文件。要是这样写[DllImport("A.dll")] 、[DllImport("B.dll")] ,还是不会加载B。用下面二中的动态加载,依然只能加载一个DLL。解决方法:把A、B复制到系统文件夹下,32位系统复制到c/windows/system32下,64位系统复制到c/windows/syswow64文件夹下,写的时候只用[DllImport("A.dll")],就会自动加载B。这种方式只适用于你可以控制电脑,如果用的别人的服务器空间,没法复制,有可能的话最好把A、B编译到一个DLL中来调用。
2、数据格式对应问题。
二、动态加载
1、用Assembly方式加载,这种方式只适用于托管代码。c++也可以编译为托管代码。依然只能加载一个DLL。
2、用LoadLibrary和GetProcAddress方式加载,这种方式可以加载非托管代码。依然只能加载一个DLL。
如下格式:
public class DllInvoke { [DllImport("kernel32.dll")] private extern static IntPtr LoadLibrary(String path); [DllImport("kernel32.dll")] private extern static IntPtr GetProcAddress(IntPtr lib, String funcName); [DllImport("kernel32.dll")] private extern static bool FreeLibrary(IntPtr lib); private IntPtr hLib; public DllInvoke(String DLLPath) { hLib = LoadLibrary(DLLPath); } ~DllInvoke() { FreeLibrary(hLib); } //将要执行的函数转换为委托 public Delegate Invoke(String APIName,Type t) { IntPtr api = GetProcAddress(hLib, APIName); return (Delegate)Marshal.GetDelegateForFunctionPointer(api,t); } }
//使用时候 public class Class1 { //定义委托变量 public delegate int C(); public ActionResult Index() { //在方法里初始化类 DllInvoke dllInvoke = new DllInvoke("DLL绝对路径"); //也可以把Dll保存在bin下,用相对路径转换为绝对路径 //调用类里面方法 C c = (C) dllInvoke.Invoke("DLL里面方法名如DogInit", typeof (C)); //得到返回值 int result = c.Invoke(); } }
三、其他方式
在搜索过程中有些关键字也有启示,但没有往下找。如更改Dll搜索目录,加入bin目录到DLL搜索顺序,DllImport加载依赖项Dll。
四、其他文章,看看
http://www.cnblogs.com/szytwo/archive/2011/12/11/2283780.html http://www.cnblogs.com/kvspas/archive/2008/12/15/1355033.html
如有地方不正确,欢迎提出。
相关文章推荐
- Jquery调用C#后台方法注意事项
- C#调用Matlab引擎详细方法以及注意事项
- Jquery调用C#后台方法注意事项
- DELPHI中调用DLL的方法和一些注意事项和技巧
- C#中调用delete方法删除datarow的一些注意
- 黑马程序员--关于C#方法的注意事项
- C++调用C#生成的DLL实现及注意事项
- HttpEntity调用getContent方法时的注意事项
- 关于PerSession下一些方法调用的注意事项
- struts 动态调用方法注意事项
- VC++调用Web Service的方法及注意事项
- ognl调用静态方法用法以及注意事项
- C#连接excel的方法与注意事项
- 脚本调用的方法及注意事项
- 字段内存C#调用C++DLL注意事项
- C#调用Oracle存储过程注意事项
- ajaxpro调用C#代码需要注意的事项(1)
- ajaxpro调用C#代码需要注意的事项(2)
- VC 调用C#写的COM组件注意事项
- C#调用C++函数的注意事项