[疑难] 新手请教问题...
player7
2007-04-18
用D语言调用C++的类,这个类是由很多虚函数组成
struct AAA{ BBB* vt; } struct BBB{ extern(Windows): void function(AAA*) test1; //原C++函数是 void test(); } ------------------------ 现在我调用时都是先取到C++类的指针给 AAA* pa; 然后: pa.vt.test1(pa); 问题1: pa.vt.test1... 这样的方式有点麻烦,如何能更好的包装成 pa.test1(AAA*)这样的? 问题2: pa.vt.test1(pa) 其中还要传入一个 AAA* 参数,这样写太麻烦了,有没有办法能改一下?因为这个类里的每个虚函数都要传入这个AAA* ,实在是无聊 最好就是能像 pa.test1() 这样就好了 |
|
qiezi
2007-04-18
D语言调用C++类是不被完整支持的,除非C++类里面的方法加了stdcall声明,因为很多C++编译器把类里面的方法调用编译为thiscall,this指针是从ECX传进去的,所以你这种方式只支持stdcall。
下面的讨论假定你调用的是stdcall方法。 想省代码也是可以的嘛,最简单的: auto pavt = pa.vt; pavt.test(...); pavt.test1(...); 当然还没解决需要多传第一个参数的问题,直观的办法是写一个wrapper类: class AAAWrap { this(AAA aaa){...} void test1(){aaa.vt.test1(&aaa);} private: AAA aaa; } 也可以用struct,用static opCall替代构造函数。 有些重复代码,可以用模板去产生代码,写一份模板就可以了,稍有点复杂,你可以试试,参考oldrev实现的DLL封装第一版。 |
|
qiezi
2007-04-18
如果C++类是现写的,你有一个取巧的办法,就是COM兼容模型:
// c++ 类 class AAA { virtual void __dont__call_me___please__dont_ask_why__shut_up__(){} virtual void __stdcall test1(){} virtual void __stdcall test2(int a){} }; // D类 extern(Windows) interface AAA { void test1(); void test2(int a); } 它们是二进制兼容的。注意这个多加的占位方法只需要在基类里出现一次。 |
|
player7
2007-04-18
哈哈,这个COM的不错,好简单啊
不过,我确实需要调用第一个函数啊. 有什么办法没有呢? 比如把 AAA*指针赋值故意偏移4个字节? struct TMP{ int* vatble; } TMP* tmp1= cast(TMP*) iGetPtr(); TMP tmp2.vatble= tmp1.vatble - 4; AAA* pa= cast(AAA*) &tmp2; 异想天开??? |
|
qiezi
2007-04-18
有点麻烦,不过你可以把第一个方法特殊处理,我在这个帖子里讲到过:
http://dlang.group.iteye.com/group/topic/1024 多翻几页,可能在后面。 |
|
oldrev
2007-04-18
不同的编译器名称重整是不一样的,C++ 还有多重继承的问题。
所以最好的办法是把 C++ 类转换回 C 函数,如: //C++ code: class Foo { public: void doSomething() {...} } extern(C) { void* NewFoo() { return (void*)(new Foo); } void Foo_doSomething(void* thiz) { Foo* o = (Foo*)thiz; o.doSomething(); } } 然后再用D包装成类.... |
|
qiezi
2007-04-18
名称重整不是问题,只要有一个NewFoo就行,用虚表来避开名称问题。这也是COM的原理。
|