重金之下,必有勇夫!要分的来。。(200分)

  • 主题发起人 主题发起人 squarevictory
  • 开始时间 开始时间
S

squarevictory

Unregistered / Unconfirmed
GUEST, unregistred user!
调用DLL里面的函数和过程
  function funName():integer;stdcall;external 'Do.dll'
如果DLL里面封装的不仅仅是实现单一功能的函数和过程,而是一些对象,我想要调用这些对象的方法和设置其属性应该怎么搞呀
 
重金之下,必有勇夫!是200美元吗?
 
如果是对象,参考COM/DCOM编程,普通DLL无法完成此类需求
 
问题: 悬赏:DLL中怎样输出类?怎样继承DLL中的类? ( 积分: 200 )
分类: Object Pascal

来自: rss, 时间: 1999-05-24 17:01:33, ID: 109707
问题的目的是:
Delphi有很多好的控件,C++Builder不能直接安装,可否将Delphi的控件作为类放在DLL中,再由C++Builder程序继承此类来使用.
如有实例通过愿再加200分奖励.

来自: xiaowind, 时间: 1999-05-25 14:57:54, ID: 109848
要在dll中用delphi的类是可以的,不过要自己写不少的代码,我劝你还是另想
办法,比如说,把vcl控件转成com控件等.

来自: rss, 时间: 1999-05-25 15:12:38, ID: 109850
有感于论坛里简单问题太多,弄个难点的给高手玩玩.
其实这个问题并不太难,也不必写不少的代码......


来自: 李颖, 时间: 1999-05-25 16:04:09, ID: 109858
DLL本身只能输出函数、方法等,是不能输出类型定义的。
类作为类型定义的一种,只能存在于Delphi内部,
编译后的可执行代码是不能引入类型定义的。
你想要继承类定义,比较好的方法是用包(Package),
将Delphi的源代码以包的形式编译后,在C++Builder上安装。
这种方法比较类似Pascal时代的TPL(Turbo Pascal Library)。
其实Borland自己也是这样共享VCL库的,C++Builder用的
就是Delphi的VCL库。

来自: rss, 时间: 1999-05-26 8:34:56, ID: 109994
NO,
DLL肯定可以输出类,我记得有书介绍方法,是Delphi程序调用DLL中的类,
很简单,但具体我忘了,所以提问!
CBuilder一定也可以,不过由于语言的差异需要一些特殊的定义,本人就是
问这个.
不用包是当然的了,DLL可以修改而不用改调用程序,包不行(实际也行但麻烦)
用Cbuilder调Delphi的DLL中的类可以更有效的整合两个工具,很有意义的.


来自: mayong, 时间: 1999-05-26 23:40:51, ID: 110142
dll 中只能输出类的虚拟对象方法,所以我觉得不能从dll中派生,
从dll中输出参见:“Delphi3从入门到精通”一书

来自: huizhang, 时间: 1999-05-27 7:27:55, ID: 110164
李颖所说的是正确的,标准DLL是不包括类的. 但是特殊的Dll(OCX,BPL)则另当别论.
依照编程规则, 即使你能够使用Dll的类, 你也必须在你的程序中包含类的说明文件.
最典型的使用DLL中的类的方法是使用Package.
Delphi的VCL可以全封不动地安装到BCB中去.

来自: rss, 时间: 1999-05-27 8:51:54, ID: 110178
当然最标准DLL中不包括类,只有函数,但MFC的DLL就可以包括任何类,任意继承类,
Delphi生成的DLL也并不是最标准的DLL,我想肯定可以使用类.
记得有一本C++Builder的书描写了在Delphi中定义类,然后在MFC中使用的例子,
MFC都行啊.
"Delphi的VCL可以全封不动地安装到BCB中去."
是吗?
我手上的Delphi控件好多没有源码,只有BPL和DCU文件,是可以放到
CBuilder的控件面板上,但无法使用?
恳请赐教!

来自: lhz, 时间: 1999-05-28 17:33:42, ID: 110478
类是可以export的,这一点毫无疑问.但是,对C++编译器来说,
要import,就必须要头文件.没有头文件是不可能在C++编译器
里引用任何库的,包括动态连接库.所以,只有BPL和DCU的控件,
除非有工具可以从DCU编译出HPP(当然这个工具可以是人),否
则不可能在BCB中使用.
要export类其实很容易,在C++编译器中,好象只要在类的定义
前面加__export就可以了,与函数一样.不知道DELPHI的语法
如何.但看DELPHI的风格,似乎只要把要用的DCU塞到DLL的工
程,然后用export all就可以了.

来自: WebBar, 时间: 1999-05-28 20:02:50, ID: 110498
记得早在 Borland C++ 4.0 的时候,我就做过 类在 DLL 中的输出,所以我知道
是完全可行的,包括所有的继承等。但在DELPHI中是否可行,如何实行,我就不知
道了。
但是,只要有这样的DLL,是可以根据它推导出整个类的公共和继承部份的接口的,
至少在BC40的时候,我就实现过,但在C++Builder中没做过,所以我就不太清楚
了。BC40是将类中的函数加在类名的后面实现的,所以一个函数名在DLL中输出时
非常长,具体如何翻译是可以试出来的,如果谁有时间的话。
Delphi 我就不知道了...

来自: WebBar, 时间: 1999-05-28 20:05:32, ID: 110500
记得早在 Borland C++ 4.0 的时候,我就做过 类在 DLL 中的输出,所以我知道
是完全可行的,包括所有的继承等。但在DELPHI中是否可行,如何实行,我就不知
道了。
但是,只要有这样的DLL,是可以根据它推导出整个类的公共和继承部份的接口的,
至少在BC40的时候,我就实现过,但在C++Builder中没做过,所以我就不太清楚
了。BC40是将类中的函数加在类名的后面实现的,所以一个函数名在DLL中输出时
非常长,具体如何翻译是可以试出来的,如果谁有时间的话。
Delphi 我就不知道了...

来自: rss, 时间: 1999-06-01 18:03:37, ID: 111391
请看此文章:

如何在C++Builder中使用Delphi 控 件
上 海 铁 道 大 学
施 江 杰
我 的 使C++Builder 使 用Delphi VCL 类 库 的 方 法 基 于Windows 中 较 通 用 的DLL方 式。 在 实 际 应 用 中 找 到 了 将VCL 控 件 转 化 为DLL 库, 在C++Builder 动 态 调 用DLL。
此 法 适 用 于 非 可 视VCL 控 件。
假令在Delphi中有一Sample 控 件,有 属 性Actived、Pro1、Pro2,欲将这个控件转到C++Builder 中 使 用。
一:Delphi 中DLL 的 制 作
在Delphi中新建一DLL项目SampleDLL,在此项目中Create一 个新的
类TTtempcomp基类为TComponent即也为一个控件,在其中加入一
个constructor Create1,但不作任何动作;

在 DLL 中 加 入 要 导 出 的 属 性 的Function
(Actived、Pro1、Pro2)&Create、Destroy 的 框 架,Exports 中 加 入 导 出的Function、Procdure 名 称;

在DLL 的 主 过 程 中 对TTempcomp 的 实 例temp1 进 行Create1,另外保 存出口和设置ExitProc;

在OpenSample 的 函 数 中 加 入 HwCtrl:= Sample1.Create(temp1) 对Sample进行实例化,对CloseSample 和 其 它 属 性 加 入 相 应 的 语 句;
二:C++Builder 中DLL 的 使 用
将Delphi 中 生 成 的DLL 用implib 生 成LIB 文 件 加 入 C++Builder 的 工 程 文 件;

在 头 文 件 中 加 入
extern "C"
__declspec(dllimport) bool _stdcall OpenSample(void);

extern "C"
__declspec(dllimport) void _stdcall
CloseSample(void);
extern "C"
__declspec(dllimport) bool _stdcall Actived (void);
extern "C"
__declspec(dllimport) int _stdcall Pro1 (void);
extern "C"
__declspec(dllimport) int _stdcall Pro2 (void);

在OpenSample 后 你 就 可 以 使 用Delphi 中 的 属 性Actived 、Pro1、Pro2
三: 参 考DLL Source 如 下:
library SampleDLL;
uses
SysUtils, Classes, Sample;
TYPE
TTempcomp = class(TComponent)
private
public
constructor Create1;
published
end;
var
Sample1 :Sample;
SaveExit :Pointer;
temp1 :TTempcomp;
constructor TTempcomp.Create1;
begin

// inherited Create(self);
end;
/==============================================
function OpenSample: Boolean; stdcall; export;
begin

HwCtrl:= Sample1.Create(temp1);
If Sample1.Actived then
result:=true;
end;
procedure CloseSample; stdcall; export;
begin

Sample1.Destroy;
end;
function Actived: Boolean; stdcall; export;
begin

result:=Sample1.Actived;
end;
function Pro1: Interger; stdcall; export;
begin

result:= Sample1.Pro1;
end;
function Pro2: Interger; stdcall; export;
begin

result:= Sample1.Pro2;

end;
/==============================================
procedure libexit; far
begin

if Sample1.Actived =true then

Sample1.Destroy;
ExitProc:=SaveExit;
temp1.Destroy;
end;
exports
OpenSample,CloseSample,Actived ,Pro1,Pro2;
begin

temp1:=TTempcomp.Create1;
SaveExit:=ExitProc;
ExitProc:=@libexit;
end.

---- 解 释:
---- 因 为VCL 控 件 都 继 承 于TComponent,TComponent 的 构 造 函 数 需 要 一 个AOwner
并 且 也 是TComponent,VCL 控 件 的Create、Destroy 都 由 控 件 的 拥 有 者 来 动 作, 也 就
是AOwner; 所 以 我 在 此DLL 中 新 设 置 了 一 个TTempcomp 类 继 承 于Tcomponent 且 性 设
置 了 一 个constructor( 构 造 函 数)Create1, 而 实 际 构 造 时 什 么 都 不 做, 以 次 作 为
要Create 的Aowner;
---- 其 他 还 有 一 种 办 法 就 是 用Application 作 为Aowner 但 是 它 是 基 于Tform 的 作
出 来 的DLL 太 大;
---- 其 实,Inprise( 原 Borland) 尽 可 以 象MicroSoft 一 样 用 一 些 象DCOM 类 似 的
组 件 形 式 使 得 产 品 在 同 一 产 品 时 代 保 持 一 定 的 互 用 性, 来 增 加 产 品 群 的 生 命 力.

来自: redforks, 时间: 1999-06-26 2:21:44, ID: 117487
请问rss,
这样的是类吗?只是类的函数封装吧!
那么,怎样在C++中创建这个类的多个实例呢?怎样在C++中派生出基于动态连接库
中的类的派生类呢?
如果把VCL做成DCOM,那就不需要VCL了,Delphi也就是VB了,COM是面向对象的吗?

来自: 视窗王子, 时间: 1999-07-01 13:07:44, ID: 118378
要做到这些极其容易,不过非常抱歉的是我只知道在VC中如何做:
#ifdef IMPAPI
#define DLLAPI __declspec(dllexport)
#else

#define DLLAPI __declspec(dllexport)
#endif
...
class ABC
{
...
DLLAPI void Test();
...
};
如果想全部输出
class DLL ABC
{
};
我特别建议使用后者并实现类自己的new,delete,new[],delete[],
原因是C runtime library(.lib)在.EXE和.DLL是两个实例。
这也是COM/OLE为何用自己的管理机制的根本原因。


来自: rss, 时间: 1999-07-08 8:35:50, ID: 119636
多人接受答案了。

得分大富翁: redforks-80,WebBar-20,xiaowind-20,视窗王子-80,
 
首先,你的分并不足说是重金
第二,我帮你并非因为自己是勇夫:):)
刚刚回答了一个类似的问题
现在重新打一遍,当作复习了
最重要一点先说明:
在DLL中实现对象,定义的对象只能引出抽象方法
结合一个例子来说
比如你要输出一个对象,里面有一个方法返回对错,那么
1.在Dll中定义一个抽象类,比如
TMyBase = class
里面所有的方法都是抽象方法和虚拟方法
如你的方法定义如下:
function ReturnResult: Boolean;
virtual;
abstract;
2.DLL中定义一个派生类实现抽象类的方法,比如
TMyChild = class(TMyBase)
使用override继承方法如下
function TMyChild.ReturnResult: Boolean;
begin
Result := True;
end;
3.在DLL中提供引出对象的函数,比如
function CreateMyObject: TMyChild;
stdcall;
begin
Result := TMyChild.Create;
end;

Exports
CreateMyObject;
4.在应用程序中重新声明该抽象类
5.应用程序中引用DLL中的输出函数
function CreateMyObject: TMyBase;
stdcall, external'../../**.dll';
6.在使用的地方如下调用
var
A: TMybase;
begin
A := CreateMyObject;
end;
然后就可以对A进行操作了
打字手酸了,楼主看着办怎么补偿啊:):)
 
To 轻舞肥羊
普通DLL也可以实现这个功能
当然使用COM更有针对性
 
这个简单啊
我写过一些代码,不光能操作dll中的内容,而且dll还可以使用exe提供的功能(比窗口的canvas,在窗口上增加菜单、按钮等等),当然这需要自己事先定义好接口(比较累),基本上算是实现程序可以进行二次开发。
 
muhx说得很清楚了,就是这样!当然用COM也是很方便的实现的
 
muhx,很感谢你的回答,”重金“,”勇夫“也只不过是个称号,表太介意。
其实我所要知道的就是第4步骤以后的事情了,DLL是现成的(C++写的),不过不管什么语言写的,既然封装成DLL,对与我进行二次开发来说,应该都是透明的。
我现在所想知道的是
1。如何声明DLL中的类。
2。如何调用类的方法。
当然,你的回答中都有提到,不过我还没试验过。今晚回家后试下。
PS:手打字打酸了是吧,今天7夕,让你女朋友给你按摩去。嘎嘎
 
你只能使用接口了~
 
可以考虑导出接口。
 
必须是注册的对象,才能调用这些对象的方法和设置其属性
 
问题解决第一步了,不过没用MUHX的方法(但是MUHX的回答还是很有启发的)
用 project-import type library引入com组件后,直接就可以在DELPHI中创建COM中的类了。
在生成的。PAS文件中会创建了2种类型,1.TClass1,2.IClass1(一种是接口类型,一种是为了实现接口的类 类型,有个高手是这样解释的,不知道对不?)
但问题2来了
在COM中有2个类Class1,Class2
var
Class1:TClass1;
Class2:TClass2;
begin
Class1:=TClass1.create(self);
Class2:=TClass2.create(self);
Class2.text:='hello';
Class1.add(Class2);
//注意,在这个时候出错了 Incompatible types:'IClass2' and 'TClass2'
end;

我估计是Class1.add方法中的参数是IClass2类型的,但是前面的Class2定义的是TClass2
如果将Class2定义为IClass2类型的,那Class2.text:='Hello'这句也会出错的。
 
对象就用UNIT应该就可以了吧
 
上面的问题我也解决了
Class1.add(Class2.DefaultInterface);
具体为什么也搞不清楚。如果有知道的高手麻烦说下呀。
后续问题,如何引用COM中的事件?
例如在COM中定义了一个事件
procedure SocketClosed(errorCode: Integer);
dispid 8;
怎么才可以在DELPHI中在触发该事件时做指定操作。
 
天那,这么久了还没人回答最后一个问题,算了还是我自己回答自己吧。
 
2006-8-2 TO 2006-8-3 工作笔记
为什么人们总是喜欢将简单的事情变复杂?
前两天接到一个由上海移动提供的短信开发包。主要功能是实现短信的发送与接收回复报告。
开发包里面提供了3种实现方式。
1.java
2.Com
3.Http
然后便选择了COM方式的。为什么?很简单,因为其它两种方式没接触过,嘿嘿。
前言:
1。先在接口部分声明引用的COM组件的接口单元文件
2。声明对象变量,类型为COM组件中的类
3。调用类中Create方法创建一对象实例
4。现在即可调用COM组件的方法了
5。使用完,调用Free方法释放该对象
这是在网上找到的关于使用COM组件的方法说明。
当然,这并不是具体的解决方案,也就是告诉你该按什么样的步骤去做。


首先,我们知道,组件有三大要素:属性,方法,事件。要使用一个组件完成一项功能首先设置其属性,然后调用其方法,最后在某项事件中编写触发该事件后所需要执行的代码。(当然,使用前必须先创建该对象)。这对于使用VCL来说是很简单的。
可是COM封装的是一些过程函数或是一些类,我们不可以象使用VCL那样,由DELPHI帮我们生成相应的代码框架。要引用COM中的类,必须先编写引用代码。在《DELPHI7程序设计与开发技术》第十五章“动态连接库和组件包”中有说明关于如何使用DLL中的过程和函数(静太调用和动态调用两种方法)。这样是可以直接引用COM中的函数和过程的。可是如果COM中封装的是类呢?我们要使用COM中的类,在DELPHI中创建该类,设置其属性,调用其方法,然后在其相应的事件中编写触发代码。
在我看过《DELPHI5开发人员指南》第二十三章“Com和ActiveX”后,便彻底地失望了。COM不就是为了方便程序员们共享不同语言编写的组件吗?那为什么在引用COM的时候还要搞得如此复杂呢。或则是这本书把本来简单的事情变复杂了。(《DELPHI5开发人员指南》一本公认的好书)。
好了,写到这里我自己都有点乱了,再写下去我怕把自己都搞复杂了。
最后用最简单的话解决问题。
1。安装COM组件
Project->Import Type Library->Add
2。使用组建的类
经过以上步骤安装好COM组件后会生成3个文件:EMPPLib_TLB.dcr,EMPPLib_TLB.dcu,EMPPLib_TLB.pas。
打开EMPPLIB——TLB.PAS,你会发现,它和VCL中的.PAS是如此的相似。很好,这个时候你就可以象声明VCL中类来声明COM中的类了。
假设COM中有一个类Socket.
var
Socket:TSocket;
begin
Socket:=TSocket.Create(self);
end;

3。设置属性,调用方法。
这还用我说吗?
4。事件。
对于如何关联COM中类的事件,我是有点生气了。在网上搜了N编资料后,发现原来很简单的事情被一些不懂装懂的,自己为自己很懂的人给搞得如此臃肿和复杂。
收拾心情,其实将COM中的事件关联到DELPHI中很简单的。你会写过程和函数吗?那好,在interface下定义一个过程(函数),过程名可以不一样,参数,返回值和COM中的事件一样。在初始化程序的时候,将刚刚定义的过程(函数)赋值给刚定义的类(Com)的事件就可以了。
例如:
Com中事件的定义:
procedure SocketClosed(errorCode: Integer);
dispid 1;
DELPHI过程的定义:
procedure Socket_OnSocketClosed(Sender:TObject;errorCode: Integer);
//记得要加Sender:TObject,否则定义的过程不能赋值给事件。
事件引用:
Socket.SocketClosed:=Socket_OnSocketClosed;
//Socket是COM中的一个类
 
希望遇到类似问题的朋友可以少走弯路。
 
多人接受答案了。
 
后退
顶部