ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C#调用C++写的dll

2022-07-26 10:34:31  阅读:145  来源: 互联网

标签:char C# void c++ dll ---- c# int C++


C#调用C++的DLL搜集整理的所有数据类型转换方式(转)   2011-04-01 13:49:13|  分类: C++,C#|举报|字号 订阅         //C++中的DLL函数原型为         //extern "C" __declspec(dllexport) bool 方法名一(const char* 变量名1, unsigned char* 变量名2)         //extern "C" __declspec(dllexport) bool 方法名二(const unsigned char* 变量名1, char* 变量名2)         //C#调用C++的DLL搜集整理的所有数据类型转换方式,可能会有重复或者多种方案,自己多测试         //c++:HANDLE(void   *)          ----    c#:System.IntPtr          //c++:Byte(unsigned   char)     ----    c#:System.Byte          //c++:SHORT(short)              ----    c#:System.Int16          //c++:WORD(unsigned   short)    ----    c#:System.UInt16          //c++:INT(int)                  ----    c#:System.Int16         //c++:INT(int)                  ----    c#:System.Int32          //c++:UINT(unsigned   int)      ----    c#:System.UInt16         //c++:UINT(unsigned   int)      ----    c#:System.UInt32         //c++:LONG(long)                ----    c#:System.Int32          //c++:ULONG(unsigned   long)    ----    c#:System.UInt32          //c++:DWORD(unsigned   long)    ----    c#:System.UInt32          //c++:DECIMAL                   ----    c#:System.Decimal          //c++:BOOL(long)                ----    c#:System.Boolean          //c++:CHAR(char)                ----    c#:System.Char          //c++:LPSTR(char   *)           ----    c#:System.String          //c++:LPWSTR(wchar_t   *)       ----    c#:System.String          //c++:LPCSTR(const   char   *)  ----    c#:System.String          //c++:LPCWSTR(const   wchar_t   *)      ----    c#:System.String          //c++:PCAHR(char   *)   ----    c#:System.String          //c++:BSTR              ----    c#:System.String          //c++:FLOAT(float)      ----    c#:System.Single          //c++:DOUBLE(double)    ----    c#:System.Double          //c++:VARIANT           ----    c#:System.Object          //c++:PBYTE(byte   *)   ----    c#:System.Byte[]         //c++:BSTR      ----    c#:StringBuilder         //c++:LPCTSTR   ----    c#:StringBuilder         //c++:LPCTSTR   ----    c#:string         //c++:LPTSTR    ----    c#:[MarshalAs(UnmanagedType.LPTStr)] string          //c++:LPTSTR 输出变量名    ----    c#:StringBuilder 输出变量名         //c++:LPCWSTR   ----    c#:IntPtr         //c++:BOOL      ----    c#:bool            //c++:HMODULE   ----    c#:IntPtr             //c++:HINSTANCE ----    c#:IntPtr          //c++:结构体    ----    c#:public struct 结构体{};          //c++:结构体 **变量名   ----    c#:out 变量名   //C#中提前申明一个结构体实例化后的变量名         //c++:结构体 &变量名    ----    c#:ref 结构体 变量名                 //c++:WORD      ----    c#:ushort         //c++:DWORD     ----    c#:uint         //c++:DWORD     ----    c#:int         //c++:UCHAR     ----    c#:int         //c++:UCHAR     ----    c#:byte         //c++:UCHAR*    ----    c#:string         //c++:UCHAR*    ----    c#:IntPtr         //c++:GUID      ----    c#:Guid         //c++:Handle    ----    c#:IntPtr         //c++:HWND      ----    c#:IntPtr         //c++:DWORD     ----    c#:int         //c++:COLORREF  ----    c#:uint         //c++:unsigned char     ----    c#:byte         //c++:unsigned char *   ----    c#:ref byte         //c++:unsigned char *   ----    c#:[MarshalAs(UnmanagedType.LPArray)] byte[]         //c++:unsigned char *   ----    c#:[MarshalAs(UnmanagedType.LPArray)] Intptr         //c++:unsigned char &   ----    c#:ref byte         //c++:unsigned char 变量名      ----    c#:byte 变量名         //c++:unsigned short 变量名     ----    c#:ushort 变量名         //c++:unsigned int 变量名       ----    c#:uint 变量名         //c++:unsigned long 变量名      ----    c#:ulong 变量名         //c++:char 变量名       ----    c#:byte 变量名   //C++中一个字符用一个字节表示,C#中一个字符用两个字节表示         //c++:char 数组名[数组大小]     ----    c#:MarshalAs(UnmanagedType.ByValTStr, SizeConst = 数组大小)]        public string 数组名; ushort         //c++:char *            ----    c#:string       //传入参数         //c++:char *            ----    c#:StringBuilder//传出参数         //c++:char *变量名      ----    c#:ref string 变量名         //c++:char *输入变量名  ----    c#:string 输入变量名         //c++:char *输出变量名  ----    c#:[MarshalAs(UnmanagedType.LPStr)] StringBuilder 输出变量名         //c++:char **           ----    c#:string         //c++:char **变量名     ----    c#:ref string 变量名         //c++:const char *      ----    c#:string         //c++:char[]            ----    c#:string         //c++:char 变量名[数组大小]     ----    c#:[MarshalAs(UnmanagedType.ByValTStr,SizeConst=数组大小)] public string 变量名;         //c++:struct 结构体名 *变量名   ----    c#:ref 结构体名 变量名         //c++:委托 变量名   ----    c#:委托 变量名         //c++:int       ----    c#:int         //c++:int       ----    c#:ref int         //c++:int &     ----    c#:ref int         //c++:int *     ----    c#:ref int      //C#中调用前需定义int 变量名 = 0;         //c++:*int      ----    c#:IntPtr         //c++:int32 PIPTR *     ----    c#:int32[]         //c++:float PIPTR *     ----    c#:float[]                //c++:double** 数组名          ----    c#:ref double 数组名         //c++:double*[] 数组名          ----    c#:ref double 数组名         //c++:long          ----    c#:int         //c++:ulong         ----    c#:int                  //c++:UINT8 *       ----    c#:ref byte       //C#中调用前需定义byte 变量名 = new byte();                 //c++:handle    ----    c#:IntPtr         //c++:hwnd      ----    c#:IntPtr                           //c++:void *    ----    c#:IntPtr                 //c++:void * user_obj_param    ----    c#:IntPtr user_obj_param         //c++:void * 对象名称    ----    c#:([MarshalAs(UnmanagedType.AsAny)]Object 对象名称                    //c++:char, INT8, SBYTE, CHAR                               ----    c#:System.SByte           //c++:short, short int, INT16, SHORT                        ----    c#:System.Int16           //c++:int, long, long int, INT32, LONG32, BOOL , INT        ----    c#:System.Int32           //c++:__int64, INT64, LONGLONG                              ----    c#:System.Int64           //c++:unsigned char, UINT8, UCHAR , BYTE                    ----    c#:System.Byte           //c++:unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR , __wchar_t             ----    c#:System.UInt16           //c++:unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT      ----    c#:System.UInt32           //c++:unsigned __int64, UINT64, DWORDLONG, ULONGLONG                            ----    c#:System.UInt64           //c++:float, FLOAT                                                              ----    c#:System.Single           //c++:double, long double, DOUBLE                                               ----    c#:System.Double         //Win32 Types        ----  CLR Type                  //Struct需要在C#里重新定义一个Struct         //CallBack回调函数需要封装在一个委托里,delegate static extern int FunCallBack(string str);         //unsigned char** ppImage替换成IntPtr ppImage         //int& nWidth替换成ref int nWidth         //int*, int&, 则都可用 ref int 对应         //双针指类型参数,可以用 ref IntPtr         //函数指针使用c++: typedef double (*fun_type1)(double); 对应 c#:public delegate double  fun_type1(double);         //char* 的操作c++: char*; 对应 c#:StringBuilder;         //c#中使用指针:在需要使用指针的地方 加 unsafe         //unsigned   char对应public   byte         /*          * typedef void (*CALLBACKFUN1W)(wchar_t*, void* pArg);          * typedef void (*CALLBACKFUN1A)(char*, void* pArg);          * bool BIOPRINT_SENSOR_API dllFun1(CALLBACKFUN1 pCallbackFun1, void* pArg);          * 调用方式为          * [UnmanagedFunctionPointer(CallingConvention.Cdecl)]          * public delegate void CallbackFunc1([MarshalAs(UnmanagedType.LPWStr)] StringBuilder strName, IntPtr pArg);          *           *           */               方法有不少,这里记录其中的一个方法。编译、调用通过了的。期间遇到的问题是C#调用时传递string类型的参数和返回值会报错。TargetInvocationException异常,值不在范围内,内存不可访问等等。 解决方法是;在c++的DLL中将string类型的参数返回值改为LPTSTR类型。在C#程序中使用StringBuilder类型来传入参数和接受返回值。 下面是代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; //1. 打开项目“Tzb”,打开类视图,右击“Tzb”,选择“添加”-->“类”,类名设置为“dld”, //即dynamic loading dll 的每个单词的开头字母。 //2. 添加所需的命名空间及声明参数传递方式枚举: using System.Runtime.InteropServices; // 用 DllImport 需用此 命名空间 using System.Reflection; // 使用 Assembly 类需用此 命名空间 using System.Reflection.Emit; // 使用 ILGenerator 需用此 命名空间 namespace WpfApplication1 { //在“public class dld”上面添加如下代码声明参数传递方式枚举: /// /// 参数传递方式枚举 ,ByValue 表示值传递 ,ByRef 表示址传递 /// public enum ModePass { ByValue = 0x0001, ByRef = 0x0002 } public class DLD { //3. 声明LoadLibrary、GetProcAddress、FreeLibrary及私有变量hModule和farProc: /// /// 原型是 :HMODULE LoadLibrary(LPCTSTR lpFileName); /// /// < param name="lpFileName" / >DLL 文件名 /// 函数库模块的句柄 [DllImport("kernel32.dll")] static extern IntPtr LoadLibrary(string lpFileName); /// /// 原型是 : FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName); /// /// < param name="hModule" / > 包含需调用函数的函数库模块的句柄 /// < param name="lpProcName" / > 调用函数的名称 /// 函数指针 [DllImport("kernel32.dll")] static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); /// /// 原型是 : BOOL FreeLibrary(HMODULE hModule); /// /// < param name="hModule" / > 需释放的函数库模块的句柄 /// 是否已释放指定的 Dll [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)] static extern bool FreeLibrary(IntPtr hModule); /// /// Loadlibrary 返回的函数库模块的句柄 /// private IntPtr hModule = IntPtr.Zero; /// /// GetProcAddress 返回的函数指针 /// public IntPtr farProc = IntPtr.Zero; //4. 添加LoadDll方法,并为了调用时方便,重载了这个方法: /// /// 装载 Dll /// /// < param name="lpFileName" / >DLL 文件名 public void LoadDll(string lpFileName) { hModule = LoadLibrary(lpFileName); if (hModule == IntPtr.Zero) throw (new Exception(" 没有找到 :" + lpFileName + ".")); } // 若已有已装载Dll的句柄,可以使用LoadDll方法的第二个版本: public void LoadDll(IntPtr HMODULE) { if (HMODULE == IntPtr.Zero) throw (new Exception(" 所传入的函数库模块的句柄 HMODULE 为空 .")); hModule = HMODULE; } //5. 添加LoadFun方法,并为了调用时方便,也重载了这个方法,方法的具体代码及注释如下: /// /// 获得函数指针 /// /// < param name="lpProcName" / > 调用函数的名称 public void LoadFun(string lpProcName) { // 若函数库模块的句柄为空,则抛出异常 if (hModule == IntPtr.Zero) throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !")); // 取得函数指针 farProc = GetProcAddress(hModule, lpProcName); // 若函数指针,则抛出异常 if (farProc == IntPtr.Zero) throw (new Exception(" 没有找到 : " + lpProcName + " 这个函数的入口点 ")); } /// /// 获得函数指针 /// /// < param name="lpFileName" / > 包含需调用函数的 DLL 文件名 /// < param name="lpProcName" / > 调用函数的名称 public void LoadFun(string lpFileName, string lpProcName) { // 取得函数库模块的句柄 hModule = LoadLibrary(lpFileName); // 若函数库模块的句柄为空,则抛出异常 if (hModule == IntPtr.Zero) throw (new Exception(" 没有找到 :" + lpFileName + ".")); // 取得函数指针 farProc = GetProcAddress(hModule, lpProcName); // 若函数指针,则抛出异常 if (farProc == IntPtr.Zero) throw (new Exception(" 没有找到 :" + lpProcName + " 这个函数的入口点 ")); } //6. 添加UnLoadDll及Invoke方法,Invoke方法也进行了重载: /// /// 卸载 Dll /// public void UnLoadDll() { FreeLibrary(hModule); hModule = IntPtr.Zero; farProc = IntPtr.Zero; } /// /// 调用所设定的函数 /// /// < param name="ObjArray_Parameter" / > 实参 /// < param name="TypeArray_ParameterType" / > 实参类型 /// < param name="ModePassArray_Parameter" / > 实参传送方式 /// < param name="Type_Return" / > 返回类型 /// 返回所调用函数的 object public object Invoke(object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter, Type Type_Return) { // 下面 3 个 if 是进行安全检查 , 若不能通过 , 则抛出异常 if (hModule == IntPtr.Zero) throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !")); if (farProc == IntPtr.Zero) throw (new Exception(" 函数指针为空 , 请确保已进行 LoadFun 操作 !")); if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length) throw (new Exception(" 参数个数及其传递方式的个数不匹配 .")); // 下面是创建 MyAssemblyName 对象并设置其 Name 属性 AssemblyName MyAssemblyName = new AssemblyName(); MyAssemblyName.Name = "InvokeFun"; // 生成单模块配件 AssemblyBuilder MyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( MyAssemblyName, AssemblyBuilderAccess.Run); ModuleBuilder MyModuleBuilder = MyAssemblyBuilder.DefineDynamicModule("InvokeDll"); // 定义要调用的方法 , 方法名为“ MyFun ”,返回类型是“ Type_Return ” //参数类型是“ TypeArray_ParameterType ” MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod( "Init", MethodAttributes.Public | MethodAttributes.Static, Type_Return, TypeArray_ParameterType); // 获取一个 ILGenerator ,用于发送所需的 IL ILGenerator IL = MyMethodBuilder.GetILGenerator(); int i; for (i = 0; i < ObjArray_Parameter.Length; i++) {// 用循环将参数依次压入堆栈 switch (ModePassArray_Parameter[i]) { case ModePass.ByValue: IL.Emit(OpCodes.Ldarg, i); break; case ModePass.ByRef: IL.Emit(OpCodes.Ldarga, i); break; default: throw (new Exception(" 第 " + (i + 1).ToString() + " 个参数没有给定正确的传递方式 .")); } } if (IntPtr.Size == 4) {// 判断处理器类型 IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32()); } else if (IntPtr.Size == 8 ) { IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64()); } else { throw new PlatformNotSupportedException(); } IL.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, Type_Return, TypeArray_ParameterType); IL.Emit(OpCodes.Ret); // 返回值 MyModuleBuilder.CreateGlobalFunctions(); // 取得方法信息 MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("Init"); return MyMethodInfo.Invoke(null, ObjArray_Parameter);// 调用方法,并返回其值 } //Invoke方法的第二个版本,它是调用了第一个版本的: /// /// 调用所设定的函数 /// /// < param name="IntPtr_Function" / > 函数指针 /// < param name="ObjArray_Parameter" / > 实参 /// < param name="TypeArray_ParameterType" / > 实参类型 /// < param name="ModePassArray_Parameter" / > 实参传送方式 /// < param name="Type_Return" / > 返回类型 /// 返回所调用函数的 object public object Invoke(IntPtr IntPtr_Function, object[] ObjArray_Parameter, Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter, Type Type_Return) { // 下面 2 个 if 是进行安全检查 , 若不能通过 , 则抛出异常 if (hModule == IntPtr.Zero) throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !")); if (IntPtr_Function == IntPtr.Zero) throw (new Exception(" 函数指针 IntPtr_Function 为空 !")); farProc = IntPtr_Function; return Invoke(ObjArray_Parameter, TypeArray_ParameterType, ModePassArray_Parameter, Type_Return); } } } /*******调用方法******/ private void button1_Click(object sender, RoutedEventArgs e) { DLD newDLL = new DLD(); newDLL.LoadFun("E:\\workspaces\\WpfApplication1\\Debug\\DLL.dll", "Init"); StringBuilder MyStringBuilder = new StringBuilder("Hello World!"); object[] obj = new object[] { MyStringBuilder }; Type[] ty = new Type[] { typeof(StringBuilder) }; ModePass[] mode = new ModePass[] { ModePass.ByValue }; Type Type_Return = typeof(StringBuilder); StringBuilder j = (StringBuilder)newDLL.Invoke(obj, ty, mode, Type_Return); } /********c++DLL中的函数*******/ extern "C" __declspec(dllexport) LPTSTR Init(LPTSTR a); LPTSTR Init(LPTSTR a) { strcat((char *)a, "added"); return a; }   c#如何调用c++的类 (2009-07-14 03:30:16) 0 转载▼
标签: 杂谈 分类: 编程技术
将c++类生成一个 .dll 文件 //-------------头文件 #pragma once   class testclass { public: testclass(void); ~testclass(void); public: WCHAR* GetName(void); }; //-------------CPP #include "StdAfx.h" #include "testclass.h"   testclass::testclass(void) { }   testclass::~testclass(void) { } WCHAR* testclass::GetName(void) { return NULL; }   //--------------接口头文件 #pragma once   #include "testclass.h"   class Insertface { public: Insertface(void); ~Insertface(void); public: void* CreateTextClass(void); WCHAR* GetName(void *textClass); BOOL DeleteTextClass(void *textClass); }; //----------------------CPP #include "StdAfx.h" #include "Insertface.h"   Insertface::Insertface(void) { }   Insertface::~Insertface(void) { } extern "C" _declspec(dllexport) void* Insertface::CreateTextClass(void) { testclass *p = new testclass(); return (void *)p; } extern "C" _declspec(dllexport) WCHAR* Insertface::GetName(void *textClass) { return ((testclass *)textClass)->GetName(); } extern "C" _declspec(dllexport) BOOL Insertface::DeleteTextClass(void *textClass) { delete (testclass *)textClass; return TRUE; }       C++的优势在于高效灵活,C#的优势在于简单易用,两者结合起来对项目开发来说是件好事,而且C++不容易反编译,也保障了代码的安全性,如果一些核心算法使用C#编写,那么保密就是一个问题。     C++生成的DLL一般只提供函数接口,不能直接用C#调用C++写的类,这样非常不方便,于是经过半天的反复测试,终于确定了一套可行的方案,下面就是整个流程的一个范例。   (1)编写C++类Mask,类前面的extern "C" class _declspec(dllexport)这么一串修饰符是必备的,不然无法导出类。   [cpp] view plaincopyprint?
  1. //Mask类头文件mask.h  
  2. #pragma once  
  3.    
  4. extern "C" class _declspec(dllexport) Mask  
  5. {  
  6. public:  
  7.        Mask(char* inputFile,int* maskValue,int maskLength);  
  8.        virtual void Run(void);  
  9.        ~Mask(void);  
  10.    
  11. private:  
  12.        char* _inputFile;  
  13.        int* _maskValue;  
  14.        int _maskLength;  
  15. };  
  (2)Mask类内部实现,这里使用char*和int*这两个有代表性的参数,C#向C++进行参数的传递是很难弄的一步。     [cpp] view plaincopyprint?
  1. //Mask类实现文件mask.cpp  
  2. Mask::Mask(char* inputFile ,int* maskValue,int maskLength)  
  3. {  
  4.        _inputFile=new char[strlen(inputFile)+1];  
  5.        strcpy(_inputFile,inputFile);  
  6.    
  7.        _maskValue=new int[maskLength];  
  8.        _maskLength=maskLength;  
  9.        for(int i=0;i<masklength;i++)  < span="">
  10.               _maskValue[i]=maskValue[i];  
  11. }  
  12.    
  13. void Mask::Run(void)  
  14. {  
  15. }  
  16.    
  17. Mask::~Mask(void)  
  18. {  
  19.        if (_inputFile)  
  20.        {  
  21.               delete [] _inputFile;  
  22.               _inputFile=NULL;  
  23.        }  
  24.        if (_maskValue)  
  25.        {  
  26.               delete [] _maskValue;  
  27.               _maskValue=NULL;  
  28.        }  
  29. }  
  可以设置生成类型为DLL,然后将debug目录下的dll文件和lib文件找到,留待下一步使用。     (3)编写C++.NET类MaskCLR,C++.NET我一直认为就是个摆设,没想到也能派上用场,难得啊,也不完全是个废物。MaskCLR可以调用Mask类,注意函数的参数已经变成String ^和int*,现在是.NET环境,使用指针没那么方便了。   [cpp] view plaincopyprint?
  1. //MaskCLR类头文件,用来包装Mask类MaskCLR.h  
  2. #pragma once  
  3. #include " mask.h"        //这个就是上面的Mask头文件  
  4.    
  5. public ref class MaskCLR  
  6. {  
  7. private:  
  8.        char* _inputFile;  
  9.        int* _maskValue;  
  10.        int _maskLength;  
  11.    
  12. public:  
  13.        MaskCLR(String ^ inputFile,int* maskValue,int maskLength);  
  14.        virtual void  Run(void) override;  
  15. };  
  (4)MaskCLR类内部实现,首先要处理参数类型问题,将String ^类型转为char*。在MaskCLR:: Run函数内部调用Mask类,Mask是DLL导出的类。     [cpp] view plaincopyprint?
  1. // MaskCLR类内部实现MaskCLR.cpp  
  2. #include "MaskCLR.h"  
  3.    
  4. MaskCLR::MaskCLR(String ^ inputFile,int* maskValue,int maskLength)  
  5. {  
  6.        _inputFile=GlobeFunction::StringToChar(inputFile);  
  7.        _maskValue=maskValue;  
  8.        _maskLength=maskLength;  
  9. }  
  10.    
  11. void MaskCLR:: Run(void)  
  12. {  
  13.        Mask mask(_inputFile, _maskValue,_maskLength);  
  14.        mask.Run();                    
  15. }  
  (5)将String ^类型转为char*,可以利用StringToHGlobalAnsi这个.NET自带的函数。     [csharp] view plaincopyprint?
  1. char* GlobeFunction::StringToChar(String ^str)  
  2. {  
  3.        return (char*)(Marshal::StringToHGlobalAnsi(str)).ToPointer();  
  4. }  
    (6)最终生成了两个DLL文件,一个是原始C++编写的,另一个是托管C++编写的,托管dll只是个外壳,最终还是调用原始dll,因此这两个dll要放在一起。下面终于进入C#环境了,首先将托管dll添加引用到C#工程中,C++.NET和C#可以直接互用。   (7)由于有个int*类型参数,在C#里指针属于不安全代码,因此使用unsafe关键字将涉及到指针的代码包括起来,在工程属性里设置允许使用不安全代码。定义int指针需要使用stackalloc关键字,创建一个int数组,对数组赋值后,将指针传递给类函数。 [csharp] view plaincopyprint?
  1. //c#调用托管dll中的MaskCLR类form1.cs  
  2. unsafe  
  3. {  
  4.        int* value = stackalloc int[1];  
  5.        value[0] = 0;  
  6.        MaskCLR mask = new MaskCLR("D:\\临时\\mask8.tif", value, 1);  
  7.        mask.Run();  
  8. }  
  (8)至此大功告成,可以用C#很方便的调用C++写的类了,如果觉得有用,不要忘了给我留言啊!!O(∩_∩)O~    

标签:char,C#,void,c++,dll,----,c#,int,C++
来源: https://www.cnblogs.com/devgis/p/16519969.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有