COMMUNITY

How to prevent copying and deleting extern c++ member variables?

haxe-cpp

(Thomas J Webb) #1

If I make an extern class that points to a c++ class like so:

@:build(Include.xml('BuildFile'))
@:include("./include/cppclass.h")
@:native("CppClass")
@:structAccess
extern class CppClass {
  @:native("CppClass")
  public static function create():CppClass;
  public function callF(callback:cpp.Callable<(a:Int, b:Float)->Void>):Void;
}

It works fine if I use it directly like so:

var cppClass = CppClass.create();
cppClass.callF(cpp.Callable.fromStaticFunction(callback));

But if I make it a member variable on another, ordinary haxe class, simply calling a method on it, calls the copy constructor:

class EncapsulatingClass {
  private var cppClass:CppClass;
  
  private static function callback(a:Int, b:Float) {
    trace(a);
    trace(b);
  }

  public function new() {
    cppClass = CppClass.create();
    cppClass.callF(cpp.Callable.fromStaticFunction(callback));
  }
}

class Main {

  public static function main() {
    trace('hello');
    var c = new EncapsulatingClass();
  }
}

Gives me this output:

destructor called
Main.hx:25: hello
destructor called
Main.hx:7: 3
Main.hx:8: 2.29999995231628
destructor called

I get why the first and second ones happen. It gets instantiated once, then again upon my create() (and to my knowledge haxe doesn’t give you a way to specify what goes in the initialization list). I can get around some of the creates by making it a pointer. However, even if I do that, making it a cpp.Pointer<CppClass>, calling a method on it requires me to do cppClass.ref.methodName(), it still ends up copying it and the local gets destructed which causes me trouble with the lib I’m currently trying to integrate. That happens because calling ref dereferences the pointer before returning it.

You can see in the generated c++ where this happens:

HXLINE(  12)            this->cppClass = CppClass();
HXLINE(  13)             CppClass _hx_tmp = this->cppClass;
HXDLIN(  13)            _hx_tmp.callF(::cpp::Function< void (int,Float)>(hx::AnyCast(&::EncapsulatingClass_obj::callback )));

And again, even if I make the member variable a cpp.Pointer instead, I still get the unnecessary copying and deletion.

You can get the whole working/non-working code at a separate branch I made of a sample extern here: