(关于.NET对旧程序的兼容的问题)c#中如何调用VC++6.0写的DLL?
我已经有一个VC++6.0写的DLL,他实现了比较复杂的功能,其中有一个专家系统。现在想把它做成webService。我想把它封装成一个C#做的DLL这样在webService中就可以直接引用了。我知道可以用DllImport把函数引进来,但是Dll导出的是一个类,怎样把这个类引进来呢?应为类中的成员函数和变量都有用呀! 问题点数:30、回复次数:31Top
1 楼antiking(生活就象拉大便有时顺畅有时不顺畅.)回复于 2006-05-01 16:52:15 得分 0
calss ss = new class();Top
2 楼shiyubeijing()回复于 2006-05-01 21:05:51 得分 0
-_-不太明白,calss ss = new class();这个class从哪里来总得说明白吧!
如果是一个函数可以用如下方法把vc++的dll的导出函数fun1引入到c#中:
[DllImport("MyDll.dll",EntryPoint="fun1")]
public static extern int fun1(int a, int b);
但是怎样才能把vc++写的dll的类导入呢?antiking(Q狼E行)说的我不太明白......Top
3 楼shiyubeijing()回复于 2006-05-01 22:58:24 得分 0
急切等待中。。。请高手指点!Top
4 楼Knight94(愚翁)回复于 2006-05-02 09:23:15 得分 20
如果你用DllImport是在C#类库的话,那么在webservice工程中直接添加引用即可使用。Top
5 楼shiyubeijing()回复于 2006-05-02 13:31:35 得分 0
Knight94(愚翁)你是不是说可以在webService工程中右键->添加引用?我用的式VS.NET2003,这时会弹出对话框,有三种类型可以被添加:.NET,com和项目。如果直接想把VC++6的DLL引入的话,VS弹出对话框说“这不是有效的.NET程序集,...请确保该文件可以被访问并且是有效的程序集或COM组件”!所以是不能在工程中直接对VC++6的DLL引用。不知愚翁的意思我理解对了没?Top
6 楼Knight94(愚翁)回复于 2006-05-02 13:52:24 得分 0
当然不是这个意思Top
7 楼Knight94(愚翁)回复于 2006-05-02 13:54:41 得分 0
不过你调用vc6的dll中以类返回,是有些麻烦Top
8 楼shiyubeijing()回复于 2006-05-02 20:44:10 得分 0
呵呵,连愚翁都这么说,看来真的不好弄了。。。
不知c#的平台调用是否就是==DllImport,是否只是引入非托管的函数而不能引入类,如果真的如此我就不能再看平台调用了。但是还有什么办法呢?
急呀!难道大家都没有遇到过或是考虑这样的问题吗?请大家给个法子呀!Top
9 楼Knight94(愚翁)回复于 2006-05-03 08:24:09 得分 0
你在vs环境下的dos去用dumpbin来输出你的dll,是否能看到dll输出的函数。
还有,你能把dll中的头文件贴一部分,让我看看。Top
10 楼soaringbird()回复于 2006-05-03 09:06:55 得分 10
以前曾经用空类的方式,在VC和Delphi之间共享过类,但这种方式在C#和VC之间行不行。Top
11 楼shiyubeijing()回复于 2006-05-03 15:38:13 得分 0
以下是我的dumpbin的部分结果:
>dumpbin -exports ExpertSystem.dll
Dump of file ExpertSystem.dll
File Type: DLL
Section contains the following exports for ExpertSystem.dll
00000000 characteristics
44331D00 time date stamp Wed Apr 05 09:27:28 2006
0.00 version
1 ordinal base
25 number of functions
25 number of names
ordinal hint RVA name
1 0 000011F9 ??0CExpert@@QAE@XZ
2 1 00001221 ??1CExpert@@QAE@XZ
3 2 00001294 ?AssertActionData@CExpert@@IAEXXZ
4 3 0000128F ?AssertInputData@CExpert@@IAEXXZ
5 4 00001235 ?ChooseClipsName@CExpert@@QAEXVCString@@@Z
6 5 0000101E ?CommendWeapon@CExpert@@QAEXH@Z
7 6 000010EB ?Execute@CExpert@@QAEXXZ
......
23 16 000011A4 ReportMemoryProblems
24 17 00001244 capturePrint
25 18 0000124E captureQuery
Summary
1000 .data
1000 .idata
2000 .rdata
1000 .reloc
1000 .rsrc
22000 .textTop
12 楼shiyubeijing()回复于 2006-05-03 15:45:17 得分 0
这是我的Dll的头文件的一部分,有删节:
#include "Clipsmfc.h"
class _declspec(dllexport) CExpert
{
public:
void CommendWeapon(int target);
void GetWarning(int WarningID,float Data);
void ChooseClipsName(CString ClipsName);
void Execute();
struct Result
{
char name;
int action;
int target;
int weapon;
int method;
int direction;
int order;
};
struct Defense
{
int type;
int mode;
};
struct Input
{
PlaneState PlaneState_1;
PlaneState PlaneState_2;
PlaneState PlaneState_3;
PlaneState PlaneState_4;
Defense PlaneDefense;
};
struct Output
{
Result Result_1;
Result Result_2;
Result Result_3;
Result Result_4;
int maneuver;
};
struct Warning
{
int Weather;
float Wind_Direction;
float Horizontal_Wind_Speed;
float Static_Temperature;
float Static_Air_Pressure;
float Electromagnetism_State;
float Infrared_State;
int AlarmID;
float GASM_1;
float GASM_2;
float GASM_3;
float GASM_4;
};
struct WarningOut
{
int WarningID;
bool Result;
};
struct Weapon
{
int target;
int FirstWeapon;
int SecondWeapon;
int ThirdWeapon;
};
Input InputData;
Output OutputData;
Warning WarningData;
WarningOut WarningOutData;
Weapon WeaponCommended;
CExpert();
~CExpert();
private:
CCLIPSWrap * m_pClips;
CStringArray m_standard;
CStringArray m_outNum;
CStringArray m_outDef;
CStringArray m_outAct;
protected:
void ReadAction();
......
void WarnWeather(int Data);
BOOL RunClips();
void AssertInputData();
void ReleaseClips();
BOOL InitClips();
void ReadResult();
CString m_ClipsFileName;
};
Top
13 楼shiyubeijing()回复于 2006-05-03 15:53:16 得分 0
请看函数void CommendWeapon(int target);他的输入是一个int型的target变量;再看结构体struct Weapon
{
int target;
int FirstWeapon;
int SecondWeapon;
int ThirdWeapon;
};
在函数的具体实现中通过CommendWeapon这个函数就可以给出最后的结果保存在struct Weapon中。CommendWeapon这个函数是没有返回值的,他的作用是得到一个类中的结构体。那如果仅仅用[DllImport(...)]引入这个函数而没办法得到结果即那个结构体是不行的呀。不知我说清楚了没有?Top
14 楼Knight94(愚翁)回复于 2006-05-03 18:53:21 得分 0
在dll中返回其定义的struct类型对象是没有什么问题,只要在c#中进行声明一个一样的struct,并进行序列化即可;但是所有的函数都是用类的成员函数输出,这是比较麻烦的。而且你的dll用dumpbin进行输出是乱码,这样通过dllimport是无法找到入口。
你可以用vc.net来引入要简单些。Top
15 楼shiyubeijing()回复于 2006-05-03 20:22:56 得分 0
哦,用“序列化”?!我再看看!
真的感谢Knight94(愚翁) !谢谢!
另外我很想知道用VC++.NET真的会简单很多吗?那如果用VC++.NET会用到哪方面的知识呢?是不是C++托管还是C++/CLI?如果C#不是很复杂或是可能遇到更多的问题那我就继续弄下去了。
另外,虽然dumpbin是乱码,但是还是能一一对应的,如?CommendWeapon@CExpert@@QAEXH@Z就是CommendWeapon,dllImport时只要指定entrypoint=“?CommendWeapon@CExpert@@QAEXH@Z”还是可以找到入口点的(尽管可能笨了点或是不规范)。Top
16 楼shiyubeijing()回复于 2006-05-03 22:01:31 得分 0
序列化!!!看了一些序列化的东西,有点晕。。。
愚翁能否结合这个CommendWeapon函数和结构体Weapon给出个序列化的实例呢?这样方向明确一点。再次谢谢!Top
17 楼Knight94(愚翁)回复于 2006-05-04 08:32:20 得分 0
to 另外我很想知道用VC++.NET真的会简单很多吗?那如果用VC++.NET会用到哪方面的知识呢?是不是C++托管还是C++/CLI?如果C#不是很复杂或是可能遇到更多的问题那我就继续弄下去了。
因为你用vc.net调用dll要方便些,至少类似于指针方面的操作,要灵活多了。假如你如果dll的有.h以及.lib文件,就更方便了,直接在vc.net工程中引入.h,编译的时候加上.lib就可以了。
Top
18 楼Knight94(愚翁)回复于 2006-05-04 08:44:24 得分 0
to 能否结合这个CommendWeapon函数和结构体Weapon给出个序列化的实例呢?这样方向明确一点。再次谢谢!
[StructLayout(LayoutKind.Sequential)]
public struct Weapon
{
int target;
int FirstWeapon;
int SecondWeapon;
int ThirdWeapon;
}
那么如上的Weapon就可以在调用dll函数中进行使用了。
to void CommendWeapon(int target)的调用
如果不是class的成员函数的话,那么调用非常简单,如下:
[DllImport(...)]
public extern static void CommendWeapon( int target )
但是如果是类的成员函数的话,就比较麻烦了,要做的操作大致如下:
首先需要创建一个类的对象,然后找到函数table,再找到相应的函数项,最后再调用。
以上的操作在c#中很麻烦。Top
19 楼shiyubeijing()回复于 2006-05-04 09:37:47 得分 0
其实我是想把那个Dll实现的复杂功能弄成一个web服务,不管是C#还是vc++.net哪个方便用哪个。只是据我了解VC++.NET调用以前的dll需要用什么C++托管扩展,现在好像又新出了C++/CLI,好像也不简单。所以我才试着用C#。能轻松的把.h和.lib包含进去就能用Dll吗?如果真的那样我这么长时间就白弄了!Top
20 楼soaringbird()回复于 2006-05-04 09:53:47 得分 0
楼主,看到了你的消息,我是这么做的,比如以你的CExpert为例,在c++代码的dll代码中CExpert的定义,还应该有一个函数用以返回一个CExpert实例,比如CExpert CreateExpert,这个函数要export出来供别的语言使用。在C#中也声明一个同样的CExpert类,但它的方法要写成纯虚的,同时把CExpert CreateExpert函数import进来,就可以用CExpert expert=CreateExpert(...)来创建CExpert的实例了,然后也可以调用其方法什么的。这种方式我在VC和Delphi之间用过,但VC和C#间能不能用就不太清楚了。Top
21 楼Knight94(愚翁)回复于 2006-05-04 09:56:14 得分 0
to 能轻松的把.h和.lib包含进去就能用Dll吗?
没问题Top
22 楼Knight94(愚翁)回复于 2006-05-04 10:07:02 得分 0
.lib与.dll,一个是静态的,一个是动态的,实现的功能都是一样的。Top
23 楼shiyubeijing()回复于 2006-05-05 15:24:28 得分 0
soaringbird()的方法给了我一些启发,不知对不对:
既然DllImport可以调用Dll里的函数,而要想把dll类中的成员变量引进来比较麻烦。那我可不可以在Dll中稍加改造:我创建一个静态的成员函数,这个成员函数可以创建dll类的实例并且返回这个实例,那我在C#里可以用DllImport引入这个创建实例的静态函数就行了!这样在C#里就有了Dll中的类的实例,这样调用方法和成员变量不就都行了吗?不知这样对吗?
还有一个关键问题就是在C#里必须写一个和Dll中的类一样的类!这个是必须的吧,但是该怎么写呢?以下面这个例子为例:Top
24 楼shiyubeijing()回复于 2006-05-05 15:26:16 得分 0
以这个简单的Dll的代码为例,在C#里应该怎样写那个虚拟的类呢?
class _declspec(dllexport) MyClass
{
private:
MyClass()
{
}
public:
static MyClass createInstance()
{
MyClass a;
return a;
}
public:
int result;
void add(int a, int b)
{
result = a + b;
}
};
Top
25 楼Knight94(愚翁)回复于 2006-05-05 15:35:21 得分 0
不是我打击你,即使用静态成员函数,你在dumpbin中看到也是乱码,也就是说,你用dllimport很难找到entrypoint。Top
26 楼Knight94(愚翁)回复于 2006-05-05 15:38:31 得分 0
要么你把dll输出函数和dll类分开,那么在c#中只调用dll输出函数来模拟类的成员函数操作。
要么你用vc.net去引入.h和.lib做成类库供c#调用。Top
27 楼soaringbird()回复于 2006-05-05 17:00:55 得分 0
我正在给你试呢,Delphi调用VC的类是可以的,但C#下的可能不行,有托管代码和原生代码的差别。Top
28 楼soaringbird()回复于 2006-05-05 17:08:33 得分 0
其实你也不必非得在C#里直接调用vc的dll,也可以用VC把那个dll再封装一下,做成COM组件,在C#下就可以直接用了。Top
29 楼doitnow2000(大海)回复于 2006-05-07 10:20:20 得分 0
我现在准备用第三方开发包,第三方开发包是用vc写的,但是我想在C#用使用,结果引用的时候出错了,出现:这不是有效的.NET程序集,...请确保该文件可以被访问并且是有效的程序集或COM组件”
怎么办?Top
30 楼shiyubeijing()回复于 2006-05-07 19:18:31 得分 0
呵呵,doitnow2000(大海)可能和我遇到了类似的问题,就是在.NET下使用原来旧的程序的问题。 在c#里时不能随便引用VC下的程序的,必须做点工作,我这个菜鸟现在就是在搞这个问题。soaringbird() 说把dll再次封装一下,成COM组件我觉的也可以,我试试。Top
31 楼bufan2162(永远保持前进状态)回复于 2006-05-07 20:42:04 得分 0
顶,学习Top




