理论上将是应该可以实现的,可以考虑,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
char )
virtual
cdecl
abstract;
function getMessageLen:Integer
virtual
cdecl
abstract;
procedure sayHello
overload
virtual
cdecl
abstract;
procedure sayHello( msg
char )
overload
virtual
cdecl
abstract;
procedure free
virtual
cdecl
abstract;
end;
PHelloWorld = ^HelloWorld;
function GetHelloWorld
HelloWorld
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;
但是运行失败!!!WHY???