vc的dll如何调用(200分)

  • 主题发起人 知北游
  • 开始时间

知北游

Unregistered / Unconfirmed
GUEST, unregistred user!
vc中.def文件
;
test.def : Declares the module parameters for the DLL.
LIBRARY "test"
DESCRIPTION 'test Windows Dynamic Link Library'
EXPORTS
;
Explicit exports can go here
Msg1
Msg2
Msg3
具体函数
void Msg3(char *p)
{
char *buf = p ;
for(int i=0;i<9;i++)
buf='9';
buf = '/0' ;

}
void Msg2(UCHAR *p)
{
UCHAR *buf = p ;
for(int i=0;i<9;i++)
buf='9';
buf = '/0' ;

}
void Msg1(CString str)
{
AfxMessageBox(str);
}
在delphi中如何调用呢?最好上机实践一下。
 
理论上将是应该可以实现的,可以考虑,C++/ObjPascal 都支持虚基类,
既都具有 vtab, 那么我使用Pascal 定义一个相同的 vtab, 通过一个
全局的函数来获取这个 vtab 就可以了,然后该类就能为Pascal使用。
让我们先从 C++ 的角度测试以下,测试的代码如下:
DLL(VC)
----------------------------------------------------------------
#ifndef __SIMPLY_INC__
#define __SIMPLY_INC__
#ifdef __EXPORTS__
#define CLASS_IMPL __declspec( dllexport )
#else
#define CLASS_IMPL
#endif
class CLASS_IMPL HelloWorld {
private:
char message[1024];
public:
HelloWorld();
~HelloWorld();
virtual void __cdecl setMessage( char *msg );
virtual int __cdecl getMessageLen( void );
virtual void __cdecl sayHello( void );
virtual void __cdecl sayHello( char *msg );
virtual void __cdecl free( void );
};
extern "C" CLASS_IMPL HelloWorld *GetHelloWorld( void );
#endif //__SIMPLY_INC__
--------------------------------------------------------------
#include <windows.h>
#include "simply.h"
HelloWorld::HelloWorld()
{
lstrcpy( message, "Hello World!" );
MessageBox( 0, "Constrcuct class", "HelloWorld::HelloWorld()", MB_OK );
}
HelloWorld::~HelloWorld()
{
MessageBox( 0, "Destory class", "HelloWorld::~HelloWorld()", MB_OK );
}
void HelloWorld::setMessage( char *msg )
{
lstrcpy( message, msg );
}
int HelloWorld::getMessageLen( void )
{
return lstrlen( message );
}
void HelloWorld::sayHello( void )
{
::MessageBox( 0, message, "void HelloWorld::sayHello( void )", MB_OK );
}
void HelloWorld::sayHello( char *msg )
{
::MessageBox( 0, msg, "void HelloWorld::sayHello( char *msg )", MB_OK );
}
void HelloWorld::free( void )
{
delete this;
}
extern "C" CLASS_IMPL HelloWorld *GetHelloWorld( void )
{
return new HelloWorld;
}
——————————————————————————————
下面是测试上面DLL的C++代码:(VC)
#include <windows.h>
class HelloWorld {
public:
virtual void __cdecl setMessage( char *msg );
virtual int __cdecl getMessageLen( void );
virtual void __cdecl sayHello( void );
virtual void __cdecl sayHello( char *msg );
virtual void __cdecl free( void );
};
extern "C" HelloWorld *GetHelloWorld( void );
int main( int argc, char *argv[] )
{
HelloWorld *hw;
hw = GetHelloWorld();
hw->sayHello();
hw->sayHello( "This is my message!" );
hw->setMessage( "Hello Supper Ligang!!!" );
hw->sayHello();
hw->free();
return 0;
}
运行结果是正确的。
然后我们用Borland C++Builder 做一个从C++ 到Pascal的中间测试,
既用C++Builder使用上面动态链接库的输出类:(C++Builder)
class HelloWorld {
public:
virtual void __cdecl setMessage( char *msg );
virtual int __cdecl getMessageLen( void );
virtual void __cdecl sayHello( char *msg );
virtual void __cdecl sayHello( void );
virtual void __cdecl free( void );
};
extern "C" HelloWorld *GetHelloWorld( void );
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HelloWorld *hw;
hw = GetHelloWorld();
hw->sayHello();
hw->sayHello( "This is my message!" );
hw->setMessage( "Hello Supper Ligang!!!" );
hw->sayHello();
hw->free();
}
也是可以通过的,但你没有注意到,在C++Builder的HelloWorld
声明中 sayHello 两个成员函数的顺序和 VC 中的不同,我认为
可能是 vtab 的排序规则不同(???????????????????????????)。
现在再试一下Pascal, 下面是Delphi关于vtab的描述:
The layout of a VMT is shown in the following table.
At positive offsets, a VMT consists of a list of 32-bit
method pointers梠ne per user-defined virtual method in
the class type梚n order of declaration. Each slot contains
the address of the corresponding virtual method抯 entry point.
This layout is compatible with a C++ v-table and with COM.
At negative offsets, a VMT contains a number of fields that
are internal to Object Pascal抯 implementation. Applications
should use the methods defined in TObject to query this information,
since the layout is likely to change in future implementations of
Object Pascal.
所以理论上是可行的:
HelloWorld = class(TObject)
public
procedure setMessage( msg:pchar );
virtual;
cdecl;
abstract;
function getMessageLen:Integer;
virtual;
cdecl;
abstract;
procedure sayHello;
overload;
virtual;
cdecl;
abstract;
procedure sayHello( msg:pchar );
overload;
virtual;
cdecl;
abstract;
procedure free;
virtual;
cdecl;
abstract;
end;
PHelloWorld = ^HelloWorld;
function GetHelloWorld:pHelloWorld;
cdecl;
external 'simply.dll' name 'GetHelloWorld';
procedure TForm1.Button1Click(Sender: TObject);
var
hw: PHelloWorld;
begin
hw := GetHelloWorld();
hw.sayHello;
hw.sayHello( PChar('This is my message!') );
hw.setMessage( PChar('Hello Supper Ligang!!!') );
hw.sayHello;
hw.free;
end;
 
可以用WinExec, ShellExcute, CreateProcess等API函数启动VC程序, 启动后找到
他的hWnd, 然后可以发送消息进行控制. 具体这几个函数以及消息的使用都可以在已答或正在讨论的问题中找到.
如果VC的程序还没完成, 建议他们做成DLL文件, 调试的时候可以各自用自己的临时
界面, 最后拼装时进行DLL调用. 即做成Exe文件也可以让他们Export几个控制函数,
以便你的控制.
还可以让他们的程序做成ActiveX控件, 那就更容易拼装与调试了.
数据传递可以通过DLL的参数或者使用磁盘文件.
 
可以用DDE或DLl或粘帖板或OLE;
粘帖板主要用来传送数量较小的数据;
 

Similar threads

I
回复
0
查看
427
import
I
I
回复
0
查看
827
import
I
I
回复
0
查看
740
import
I
I
回复
0
查看
690
import
I
I
回复
0
查看
763
import
I
顶部