C#调用C++ Dll

来源:互联网 发布:seo外包公司 编辑:程序博客网 时间:2024/06/18 14:02

在C#中调用C++的DLL,可以实现高级功能,使用方法和注意事项记录如下:

博主主页:http://blog.csdn.net/xs1102

博文地址:http://blog.csdn.net/xs1102/article/details/73695949

方括号中DllImport的标记,类似于调用构造函数、类方法和类属性等。

函数的声明必须使用extern关键字,必要时也可以使用unsafe关键字,来直接使用指针传参。

对于WinAPI中的函数方法声明时不用以A或W结尾,C#字符串编码默认为多字节字符串。即相当于 char* 而不是 wchar_t* 。

例:

[DllImport("Kernel32.dll",EntryPoint="GetPrivateProfileString")]private static extern int GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName);

类型对应关系:

  • DWORD = uint

  • BOOL=bool

  • 预定义常量=enum

  • 结构=struct

  • char* = string (或StringBuilder)

    注意事项:

  • 1、DWORD必须对应int或uint,对应ulong时会导致参数传递错误。

  • 2、当char*参数用来返回字符串时,必须使用StringBuilder,string无法正常写入字符串

  • 3、当DLL使用C规范编译时,须使用CallingConvention = CallingConvention.Cdecl参数,否则调用失败

    附录:

    1、DllImport的函数声明:

    [AttributeUsage(AttributeTargets.Method)]public class DllImportAttribute: System.Attribute{    public DllImportAttribute(string dllName) {…} //定位参数为dllName    public CallingConvention CallingConvention; //入口点调用约定    public CharSet CharSet;                                   //入口点采用的字符接    public string EntryPoint;  //入口点名称    public bool ExactSpelling;   //是否必须与指示的入口点拼写完全一致,默认false    public bool PreserveSig;  //方法的签名是被保留还是被转换    public bool SetLastError;  //FindLastError方法的返回值保存在这里    public string Value { get {…} }}

    2、DllImport的函数完整定义:

    [AttributeUsage(AttributeTargets.Method, Inherited=false), ComVisible(true)]    public sealed class DllImportAttribute : Attribute    {        internal string _val;        public bool BestFitMapping;        public System.Runtime.InteropServices.CallingConvention CallingConvention;        public System.Runtime.InteropServices.CharSet CharSet;        public string EntryPoint;        public bool ExactSpelling;        public bool PreserveSig;        public bool SetLastError;        public bool ThrowOnUnmappableChar;                public DllImportAttribute(string dllName)        {            this._val = dllName;        }                internal DllImportAttribute(string dllName, string entryPoint, System.Runtime.InteropServices.CharSet charSet, bool exactSpelling, bool setLastError, bool preserveSig, System.Runtime.InteropServices.CallingConvention callingConvention, bool bestFitMapping, bool throwOnUnmappableChar)        {            this._val = dllName;            this.EntryPoint = entryPoint;            this.CharSet = charSet;            this.ExactSpelling = exactSpelling;            this.SetLastError = setLastError;            this.PreserveSig = preserveSig;            this.CallingConvention = callingConvention;            this.BestFitMapping = bestFitMapping;            this.ThrowOnUnmappableChar = throwOnUnmappableChar;        }                [SecurityCritical]        internal static Attribute GetCustomAttribute(RuntimeMethodInfo method)        {            string str;            if ((method.Attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PrivateScope)            {                return null;            }            MetadataImport metadataImport = ModuleHandle.GetMetadataImport(method.Module.ModuleHandle.GetRuntimeModule());            string importDll = null;            int metadataToken = method.MetadataToken;            PInvokeAttributes bestFitUseAssem = PInvokeAttributes.BestFitUseAssem;            metadataImport.GetPInvokeMap(metadataToken, out bestFitUseAssem, out str, out importDll);            System.Runtime.InteropServices.CharSet none = System.Runtime.InteropServices.CharSet.None;            switch ((bestFitUseAssem & PInvokeAttributes.CharSetAuto))            {                case PInvokeAttributes.BestFitUseAssem:                    none = System.Runtime.InteropServices.CharSet.None;                    break;                                case PInvokeAttributes.CharSetAnsi:                    none = System.Runtime.InteropServices.CharSet.Ansi;                    break;                                case PInvokeAttributes.CharSetUnicode:                    none = System.Runtime.InteropServices.CharSet.Unicode;                    break;                                case PInvokeAttributes.CharSetAuto:                    none = System.Runtime.InteropServices.CharSet.Auto;                    break;            }            System.Runtime.InteropServices.CallingConvention cdecl = System.Runtime.InteropServices.CallingConvention.Cdecl;            switch ((bestFitUseAssem & PInvokeAttributes.CallConvMask))            {                case PInvokeAttributes.CallConvStdcall:                    cdecl = System.Runtime.InteropServices.CallingConvention.StdCall;                    break;                                case PInvokeAttributes.CallConvThiscall:                    cdecl = System.Runtime.InteropServices.CallingConvention.ThisCall;                    break;                                case PInvokeAttributes.CallConvFastcall:                    cdecl = System.Runtime.InteropServices.CallingConvention.FastCall;                    break;                                case PInvokeAttributes.CallConvWinapi:                    cdecl = System.Runtime.InteropServices.CallingConvention.Winapi;                    break;                                case PInvokeAttributes.CallConvCdecl:                    cdecl = System.Runtime.InteropServices.CallingConvention.Cdecl;                    break;            }            bool exactSpelling = (bestFitUseAssem & PInvokeAttributes.NoMangle) != PInvokeAttributes.BestFitUseAssem;            bool setLastError = (bestFitUseAssem & PInvokeAttributes.SupportsLastError) != PInvokeAttributes.BestFitUseAssem;            bool bestFitMapping = (bestFitUseAssem & PInvokeAttributes.BestFitMask) == PInvokeAttributes.BestFitEnabled;            bool throwOnUnmappableChar = (bestFitUseAssem & PInvokeAttributes.ThrowOnUnmappableCharMask) == PInvokeAttributes.ThrowOnUnmappableCharEnabled;            return new DllImportAttribute(importDll, str, none, exactSpelling, setLastError, (method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != MethodImplAttributes.IL, cdecl, bestFitMapping, throwOnUnmappableChar);        }                internal static bool IsDefined(RuntimeMethodInfo method)        {            return ((method.Attributes & MethodAttributes.PinvokeImpl) != MethodAttributes.PrivateScope);        }                public string Value        {            get            {                return this._val;            }        }    }

    3、WinAPI中类型说明:

    • BOOL   A Boolean value.

    • BSTR   A 32-bit character pointer.

    • BYTE   An 8-bit integer that is not signed.

    • COLORREF   A 32-bit value used as a color value.

    • DWORD   A 32-bit unsigned integer or the address of a segment and its associated offset.

    • LONG   A 32-bit signed integer.

    • LPARAM   A 32-bit value passed as a parameter to a window procedure or callback function.

    • LPCSTR   A 32-bit pointer to a constant character string.

    • LPSTR   A 32-bit pointer to a character string.

    • LPCTSTR   A 32-bit pointer to a constant character string that is portable for Unicode and DBCS.

    • LPTSTR   A 32-bit pointer to a character string that is portable for Unicode and DBCS.

    • LPVOID   A 32-bit pointer to an unspecified type.

    • LRESULT   A 32-bit value returned from a window procedure or callback function.

    • UINT   A 16-bit unsigned integer on Windows versions 3.0 and 3.1; a 32-bit unsigned integer on Win32.

    • WNDPROC   A 32-bit pointer to a window procedure.

    • WORD   A 16-bit unsigned integer.

    • WPARAM   A value passed as a parameter to a window procedure or callback function: 16 bits on Windows versions 3.0 and 3.1; 32 bits on Win32.

    Data types unique to the Microsoft Foundation Class Library include the following:

    • POSITION   A value used to denote the position of an element in a collection; used by MFC collection classes.

    • LPCRECT   A 32-bit pointer to a constant (nonmodifiable) RECT structure. 

  • 原创粉丝点击