问题描述
背景:安装了一个开发包,通过开发包中的SaperaBasic类(很多类的统称)可以用C++或.net开发控制它们公司硬件的软件,SaperaBasic类包含两种类库:.net调用的和C++调用的(非托管),我需要使用.net开发(CLR,即C++.net),我选择的硬件是由一个叫SaperaRTPro类控制的,它是继承自SaperaBasic中的一两个类生成的,问题来了:因为我选的硬件不具有代表性,所以这个公司只提供了SaperaRTPro的C++类库(.h文件和DLL文件),我怎么在.net环境下,调用这个库?注:SaperaRTPro只提供了.h和SYSTEM32下安装的一些DLL,它的实现应该就是在这个DLL中,但这个DLL不是托管集,所以我在.net中不能通过引用直接调用。我会DLLIMPORT这种引用,但是我想调用整个类,不仅仅是用它的函数,这个局,怎么破?
解决方案
解决方案二:
?你不使用vc开发么?添加dll依赖,引用头文件啊。
解决方案三:
非托管的就用dllimport的方式而不是添加引用..另外调用类是什么概念?最终不都是调用类里面的方法么?
解决方案四:
托管程序不能直接访问C++类。用VC++.NET去访问,并且包装成.NET程序集。
解决方案五:
引用3楼caozhy的回复:
托管程序不能直接访问C++类。用VC++.NET去访问,并且包装成.NET程序集。
请问怎么把整个类包装成.net程序集?
解决方案六:
给你一个样例。//下列ifdef块是创建使从DLL导出更简单的//宏的标准方法。此DLL中的所有文件都是用命令行上定义的CFORCS_EXPORTS//符号编译的。在使用此DLL的//任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将//CFORCS_API函数视为是从DLL导入的,而此DLL则将用此宏定义的//符号视为是被导出的。#ifdefCFORCS_EXPORTS#defineCFORCS_API__declspec(dllexport)#else#defineCFORCS_API__declspec(dllimport)#endifstructREAD_DATA{intnLength;unsignedcharbtsData[256];};//此类是从AShura.CForCS.dll导出的classCFORCS_APICCForCS{public:CCForCS(void);CCForCS(intnValue);~CCForCS(void);public:voidPrint(LPCWSTRpszMessage);intGetValue(void);BSTRGetBSTR(intnIndex);BOOLReadData(void*pOut);intMemberValue;protected:virtualintVFunctionBefore(LPCWSTRpszMessage,int*pnValue);virtualvoidVFunctionAfter(LPCWSTRpszMessage,intnValue);private:int_nValue;};externCFORCS_APIintnCForCS;CFORCS_APIintfnCForCS(void);
//CForCS.cpp:定义DLL应用程序的导出函数。//#include"stdafx.h"#include"CForCS.h"//这是导出变量的一个示例CFORCS_APIintnCForCS=0;//这是导出函数的一个示例。CFORCS_APIintfnCForCS(void){AUTOTRACEX;return42;}//这是已导出类的构造函数。//有关类定义的信息,请参阅AShura.CForCS.hCCForCS::CCForCS():_nValue(0),MemberValue(0){AUTOTRACEX;}CCForCS::~CCForCS(){AUTOTRACEX;}CCForCS::CCForCS(intnValue):_nValue(nValue),MemberValue(nValue){AUTOTRACEX;}intCCForCS::GetValue(void){AUTOTRACEX;return_nValue+MemberValue;}BSTRCCForCS::GetBSTR(intnIndex){AUTOTRACEX;WCHARszNumber[32];swprintf_s(szNumber,_countof(szNumber),L"BSTRindex=%d.",nIndex);returnSysAllocString(szNumber);}BOOLCCForCS::ReadData(void*p){AUTOTRACEX;READ_DATArd[3];for(inti=0;i<3;++i){rd[i].nLength=(i+1)*10;for(intj=0;j<rd[i].nLength;++j){rd[i].btsData[j]=j;}}memcpy_s(p,sizeof(rd),&rd,sizeof(rd));returnTRUE;}voidCCForCS::Print(LPCWSTRpszMessage){AUTOTRACEX;intnValue=0x12345;intn=VFunctionBefore(pszMessage,&nValue);TR(L"message=%s,value=%d,CForCS=%d.",pszMessage,n,nValue);VFunctionAfter(pszMessage,nValue);}intCCForCS::VFunctionBefore(LPCWSTRpszMessage,int*pnValue){AUTOTRACEX;TR(L"Before:message=%s,value=%d,CForCS=%d.",pszMessage,_nValue,nCForCS);if(pnValue){*pnValue=nCForCS;}return_nValue;}voidCCForCS::VFunctionAfter(LPCWSTRpszMessage,intnValue){AUTOTRACEX;nCForCS=nValue;TR(L"After:message=%s,value=%d,CForCS=%d.",pszMessage,_nValue,nCForCS);}
解决方案七:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Runtime.InteropServices;namespaceAShura.CSForC{staticclassNativeImport{classDllImportedField{[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]privatestaticexternIntPtrLoadLibrary([In]stringlpFileName);[DllImport("Kernel32.dll")]privatestaticexternvoidFreeLibrary([In]IntPtrhModule);[DllImport("Kernel32.dll",CharSet=CharSet.Ansi)]privatestaticexternIntPtrGetProcAddress([In]IntPtrhModule,[In]stringlpProcName);privateIntPtrhModule;privateIntPtrptrAddress;publicDllImportedField(stringdllname,stringfieldname){hModule=LoadLibrary(dllname);ptrAddress=GetProcAddress(hModule,fieldname);}publicvoidDispose(){Dispose(true);GC.SuppressFinalize(this);}privatebooldisposed=false;protectedvirtualvoidDispose(booldisposing){if(!this.disposed){if(hModule!=IntPtr.Zero){FreeLibrary(hModule);}disposed=true;}}~DllImportedField(){Dispose(false);}publicTGetValue<T>(){return(T)Marshal.PtrToStructure(ptrAddress,typeof(T));}publicvoidSetValue<T>(Tvalue){Marshal.StructureToPtr(value,ptrAddress,false);}}privatestaticDllImportedField_nCForCS=newDllImportedField("..\..\..\Debug\CForCS.dll","?nCForCS@@3HA");publicstaticintnCForCS{get{return_nCForCS.GetValue<int>();}set{_nCForCS.SetValue(value);}}}classCVTable:IDisposable{IntPtr_vtable;publicCVTable(paramsDelegate[]methods){_vtable=Marshal.AllocHGlobal(methods.Length*Marshal.SizeOf(typeof(IntPtr)));for(inti=0;i<methods.Length;++i){Marshal.WriteIntPtr(_vtable,i*Marshal.SizeOf(typeof(IntPtr)),Marshal.GetFunctionPointerForDelegate(methods[i]));}}publicvoidDispose(){Dispose(true);GC.SuppressFinalize(this);}privatebooldisposed=false;protectedvirtualvoidDispose(booldisposing){if(!this.disposed){if(_vtable!=IntPtr.Zero){Marshal.FreeHGlobal(_vtable);_vtable=IntPtr.Zero;}disposed=true;}}~CVTable(){Dispose(false);}publicIntPtrCreateVTable(Object@this,IntPtrptrThis,intindex,intoffsetOfThis){IntPtrold=Marshal.ReadIntPtr(ptrThis,index*Marshal.SizeOf(typeof(IntPtr)));Marshal.WriteIntPtr(ptrThis,index*Marshal.SizeOf(typeof(IntPtr)),_vtable);Marshal.WriteIntPtr(ptrThis,offsetOfThis,GCHandle.ToIntPtr(GCHandle.Alloc(@this)));returnold;}publicvoidReleaseVTable(IntPtrptrThis,intindex,intoffsetOfThis,IntPtrvtable){if(ptrThis!=IntPtr.Zero){GCHandle.FromIntPtr(Marshal.ReadIntPtr(ptrThis,offsetOfThis)).Free();Marshal.WriteIntPtr(ptrThis,index*Marshal.SizeOf(typeof(IntPtr)),vtable);}}publicObjectGetThisObject(IntPtrptrThis,intoffsetOfThis){returnGCHandle.FromIntPtr(Marshal.ReadIntPtr(ptrThis,offsetOfThis)).Target;}}[StructLayout(LayoutKind.Sequential)]publicstruct_CForCS{privateIntPtr_vtable;publicint_MemberValue;privateint_nValue;}[StructLayout(LayoutKind.Sequential)]publicstruct_READ_DATA{publicintLength;[MarshalAs(UnmanagedType.ByValArray,SizeConst=256)]publicbyte[]Data;}[StructLayout(LayoutKind.Sequential)]publicstruct_READ_DATA_ARRAY{[MarshalAs(UnmanagedType.ByValArray,SizeConst=3)]public_READ_DATA[]Data;}publicclassCForCS:IDisposable{privateconststringdllname="..\..\..\Debug\CForCS.dll";privatestaticint_BaseClassSize=Marshal.SizeOf(typeof(_CForCS));privateIntPtr_basecpp;privateIntPtr_basecppvtable;privatestaticCVTable_vtable=newCVTable(new_VFunctionBeforeHandler(_VFunctionBefore_),new_VFunctionAfterHandler(_VFunctionAfter_));[DllImport(dllname,EntryPoint="??0CCForCS@@QAE@XZ",CallingConvention=CallingConvention.ThisCall)]privatestaticexternvoid_Constructor([In]IntPtr@this);publicCForCS(){_basecpp=Marshal.AllocCoTaskMem(_BaseClassSize+Marshal.SizeOf(typeof(IntPtr)));_Constructor(_basecpp);_basecppvtable=_vtable.CreateVTable(this,_basecpp,0,_BaseClassSize);}[DllImport(dllname,EntryPoint="??0CCForCS@@QAE@H@Z",CallingConvention=CallingConvention.ThisCall)]privatestaticexternvoid_Constructor([In]IntPtr@this,[In,MarshalAs(UnmanagedType.I4)]intvalue);publicCForCS(intvalue){_basecpp=Marshal.AllocCoTaskMem(_BaseClassSize+Marshal.SizeOf(typeof(IntPtr)));_Constructor(_basecpp,value);_vtable.CreateVTable(this,_basecpp,0,_BaseClassSize);}publicvoidDispose(){Dispose(true);GC.SuppressFinalize(this);}privatebooldisposed=false;[DllImport(dllname,EntryPoint="??1CCForCS@@QAE@XZ",CallingConvention=CallingConvention.ThisCall)]privatestaticexternvoid_Destructor([In]IntPtr@this);protectedvirtualvoidDispose(booldisposing){if(!this.disposed){if(_basecpp!=IntPtr.Zero){_vtable.ReleaseVTable(_basecpp,0,_BaseClassSize,_basecppvtable);_Destructor(_basecpp);Marshal.FreeCoTaskMem(_basecpp);_basecpp=IntPtr.Zero;}disposed=true;}}~CForCS(){Dispose(false);}[DllImport(dllname,EntryPoint="?Print@CCForCS@@QAEXPB_W@Z",CallingConvention=CallingConvention.ThisCall)]privatestaticexternvoid_Print([In]IntPtr@this,[In,MarshalAs(UnmanagedType.LPWStr)]stringmessage);publicvoidPrint(stringmessage){_Print(_basecpp,message);}[DllImport(dllname,EntryPoint="?GetValue@CCForCS@@QAEHXZ",CallingConvention=CallingConvention.ThisCall)][return:MarshalAs(UnmanagedType.I4)]privatestaticexternint_GetValue([In]IntPtr@this);publicintGetValue(){return_GetValue(_basecpp);}publicintMemberValue{get{returnMarshal.ReadInt32(_basecpp,(int)Marshal.OffsetOf(typeof(_CForCS),"_MemberValue"));}set{Marshal.WriteInt32(_basecpp,(int)Marshal.OffsetOf(typeof(_CForCS),"_MemberValue"),value);}}[DllImport(dllname,EntryPoint="?GetBSTR@CCForCS@@QAEPA_WH@Z",CallingConvention=CallingConvention.ThisCall)][return:MarshalAs(UnmanagedType.BStr)]privatestaticexternstring_GetGetBSTR([In]IntPtr@this,[In,MarshalAs(UnmanagedType.I4)]intindex);publicstringGetString(intindex){return_GetGetBSTR(_basecpp,index);}[DllImport(dllname,EntryPoint="?ReadData@CCForCS@@QAEHPAX@Z",CallingConvention=CallingConvention.ThisCall)][return:MarshalAs(UnmanagedType.Bool)]privatestaticexternbool_ReadData([In]IntPtr@this,[In]IntPtrdata);publicbyte[][]Data{get{intSize=Marshal.SizeOf(typeof(_READ_DATA));IntPtrptrData=Marshal.AllocHGlobal(3*Size);if(_ReadData(_basecpp,ptrData)){byte[][]d=newbyte[3][];for(inti=0;i<d.Length;++i){vardata=(_READ_DATA)Marshal.PtrToStructure(ptrData+i*Size,typeof(_READ_DATA));d[i]=newbyte[data.Length];Array.Copy(data.Data,d[i],d[i].Length);}returnd;}thrownewException();}}[DllImport(dllname,EntryPoint="?VFunctionBefore@CCForCS@@MAEHPB_WPAH@Z",CallingConvention=CallingConvention.ThisCall)][return:MarshalAs(UnmanagedType.I4)]privatestaticexternint_VFunctionBefore([In]IntPtr@this,[In,MarshalAs(UnmanagedType.LPWStr)]stringmessage,[Out,MarshalAs(UnmanagedType.I4)]outintvalue);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]privatedelegateint_VFunctionBeforeHandler([In]IntPtr@this,[In,MarshalAs(UnmanagedType.LPWStr)]stringmessage,[Out,MarshalAs(UnmanagedType.I4)]outintvalue);privatestaticint_VFunctionBefore_([In]IntPtr@this,stringmessage,outintvalue){return((CForCS)_vtable.GetThisObject(@this,_BaseClassSize)).VFunctionBefore(message,outvalue);}protectedvirtualintVFunctionBefore(stringmessage,outintvalue){return_VFunctionBefore(_basecpp,message,outvalue);}[DllImport(dllname,EntryPoint="?VFunctionAfter@CCForCS@@MAEXPB_WH@Z",CallingConvention=CallingConvention.ThisCall)]privatestaticexternvoid_VFunctionAfter([In]IntPtr@this,[In,MarshalAs(UnmanagedType.LPWStr)]stringmessage,[In,MarshalAs(UnmanagedType.I4)]intvalue);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]privatedelegatevoid_VFunctionAfterHandler([In]IntPtr@this,[In,MarshalAs(UnmanagedType.LPWStr)]stringmessage,[In,MarshalAs(UnmanagedType.I4)]intvalue);privatestaticvoid_VFunctionAfter_([In]IntPtr@this,stringmessage,intvalue){((CForCS)_vtable.GetThisObject(@this,_BaseClassSize)).VFunctionAfter(message,value);}protectedvirtualvoidVFunctionAfter(stringmessage,intvalue){_VFunctionAfter(_basecpp,message,value);}}classCSForC:CForCS{publicCSForC(){}publicCSForC(intvalue):base(value){}protectedoverrideintVFunctionBefore(stringmessage,outintvalue){intn=base.VFunctionBefore(message,outvalue);value=100;returnn;}protectedoverridevoidVFunctionAfter(stringmessage,intvalue){System.Diagnostics.Debug.WriteLine(string.Format("{0},{1}.",message,value));}}}
解决方案八:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceAShura.CSForC{classProgram{staticvoidMain(string[]args){varv=newCSForC(123456789);v.Print("CSMessage");intvalue=v.GetValue();System.Diagnostics.Debug.WriteLine(string.Format("GetValue()={0}",value));intstaticValue=NativeImport.nCForCS;System.Diagnostics.Debug.WriteLine(string.Format("StaticValue={0}",staticValue));NativeImport.nCForCS=987654321;staticValue=NativeImport.nCForCS;System.Diagnostics.Debug.WriteLine(string.Format("StaticValue={0}",staticValue));stringstringValue=v.GetString(1);System.Diagnostics.Debug.WriteLine(string.Format("StringValue()={0}",stringValue));stringValue=v.GetString(2);System.Diagnostics.Debug.WriteLine(string.Format("StringValue()={0}",stringValue));intmemberValue=v.MemberValue;System.Diagnostics.Debug.WriteLine(string.Format("MemberValue={0}",memberValue));v.MemberValue=111111111;memberValue=v.MemberValue;System.Diagnostics.Debug.WriteLine(string.Format("MemberValue={0}",memberValue));byte[][]data=v.Data;for(inti=0;i<data.Length;++i){if(data[i]!=null){for(intj=0;j<data[i].Length;++j){System.Diagnostics.Debug.Write(string.Format("{0},",data[i][j]));}System.Diagnostics.Debug.WriteLine("");}}((IDisposable)v).Dispose();}}}
解决方案九:
1、分析一下是不是一定需要这个类,能不用就不用了。2、你这个需求我认为,用clr把非托管的dll封装为.net的类库是最好的。
解决方案十:
引用8楼yinshi2006的回复:
1、分析一下是不是一定需要这个类,能不用就不用了。2、你这个需求我认为,用clr把非托管的dll封装为.net的类库是最好的。
你说的方法确实是比较靠谱的,把非托管的DLL封装为.net程序集,但是怎么封装啊?我没有这个DLL的源码
解决方案十一:
不需要得到dll源码。像普通c++程序使用dll就行。我再其他帖子里的回帖============================新建工程》visualc++》CLR》类库,语法什么的自己琢磨吧,基于C++扩展了c#里的概念,比如多了gcnew(对应C#里的new,clr里的new还是c的new)和%(用在变量声明,对应C#里的引用)等。=============================================封装出的类库,和用c#写的类库一样使用因为clr的语法说明中文的不多,熟悉一下需要4、5天。如果你英文不错,绝对可以更快。我十分推荐这样做,用它封装过sqlite,这样除了dll,稳定性和可靠性尽在掌握。