[疑难] 新手请教问题...

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的原理。
Global site tag (gtag.js) - Google Analytics