atilaneves / dpp

Directly include C headers in D source code
Boost Software License 1.0
227 stars 31 forks source link

ENH: parse C++ pure virtual function, and if a class only contains C++ pure virtual function, translate to D interface. #339

Open mw66 opened 1 year ago

mw66 commented 1 year ago
$ cat source/cpp.dpp 

class PriceBarI {
 public:
  // OHLC chart
  virtual double open_()   = 0;
  virtual double high_()   = 0;
  virtual double low_()    = 0;
  virtual double close_()  = 0;
  virtual double volume_() = 0;
  virtual int64  millis_() = 0;
};

$ ~/.dub/packages/dpp/0.5.4/dpp/bin/d++ --keep-d-files --preprocess-only --parse-as-cpp source/cpp.dpp

$ tail  source/cpp.d
class PriceBarI {
 public:
  // OHLC chart
  virtual double open_() = 0;
  virtual double high_() = 0;
  virtual double low_() = 0;
  virtual double close_() = 0;
  virtual double volume_() = 0;
  virtual int64 millis_() = 0;
};

Looks like the C++ pure virtual function is not recognized.

It will be nice to parse C++ pure virtual function, and if a class only contains C++ pure virtual function: 1) translate to D interface 2) translate C++ pure virtual functions to D abstract methods.

Then it will be easier to interface D and C++:

https://dlang.org/spec/cpp_interface.html#using_d_classes_from_cpp

so the expected output are:

extern (C++) {                                                                                                                                                                                                          
interface PriceBarI {                                                                                                                                                                                                   
 public:                                                                                                                                                                                                                
  // OHLC chart                                                                                                                                                                                                         
  abstract double open_();                                                                                                                                                                                              
  abstract double high_();                                                                                                                                                                                              
  abstract double low_();                                                                                                                                                                                               
  abstract double close_();                                                                                                                                                                                             
  abstract double volume_();                                                                                                                                                                                            
  abstract long millis_();                                                                                                                                                                                              
};                                                                                                                                                                                                                      
}    

This example can be used as unittest case.

atilaneves commented 1 year ago

cpp.dpp has C++ code in it. That's not going to work.

mw66 commented 1 year ago

Sorry about that, after I move cpp.dpp to cpp.h, and create new cpp.dpp:

$ cat cpp.dpp 
#include "cpp.h"

the output is:

    class PriceBarI
    {
    private:
            public:

        pragma(mangle, "_ZN9PriceBarI5open_Ev") abstract double open_() @nogc nothrow;

        pragma(mangle, "_ZN9PriceBarI5high_Ev") abstract double high_() @nogc nothrow;

        pragma(mangle, "_ZN9PriceBarI4low_Ev") abstract double low_() @nogc nothrow;

        pragma(mangle, "_ZN9PriceBarI6close_Ev") abstract double close_() @nogc nothrow;

        pragma(mangle, "_ZN9PriceBarI7volume_Ev") abstract double volume_() @nogc nothrow;

        pragma(mangle, "_ZN9PriceBarI7millis_Ev") abstract c_long millis_() @nogc nothrow;
    }

This is largely correct.

However, it would be nice if a class only contains C++ pure virtual function: 1) translate to D interface 2) can we add option to make @nogc nothrow optional? the reason is that these attribute are transitive, sometimes the method implementation need to call 3rd party library function which is not marked as nogc nothrow, while the developers has no control to change.

atilaneves commented 1 year ago

Those would be nice additions. PRs welcome.