SOLVED HxCpp: Basic extern problem

EDIT
The problem was caused by wrongly using @:extern("Greeter") instead of @:native("Greeter*") in the Greeter.hx extern file. Thanks Aidan for pointing out!
EDIT END

I’m trying a very basic example using externs for .cpp files, and everything works fine except for the problem described further below:

// src/Greeter.cpp

#include <iostream>

class Greeter
{
  public:
  void sayHello () {
        std::cout << "Greeter saying \"Hello!\" \n";        
    }

  void sayGoodbye () {
        std::cout << "Greeter saying \"Goodbye!\" " << std::endl;        
    }
};
// src/Greeter.hx

@:include("./Greeter.cpp")
@:extern("Greeter")
extern class Greeter {
	@:native("new Greeter") public static function create():Greeter;

	@:native("sayHello") public function sayHello():Void;
	@:native("sayGoodbye") public function sayGoodbye():Void;
}
# build.hxml

-cp src
-D analyzer-optimize
-main Main
-cpp out

Compiling and running with the following Main.hx works fine, and gives the expected output…

// src/Main.hx

class Main {
	static function main() {
		final greeter:Greeter = Greeter.create();

		// Uncommenting one of the lines below works fine
		// Uncommenting both - Causes compile error!
		
		greeter.sayHello();		
		//greeter.sayGoodbye(); 
	}
}

The strange thing is that as soon as I uncomment BOTH of the greeter.sayHello() and greeter.sayGoodbye() lines, the program won’t compile. (It works fine with just any of them.)
Tried on both macOS and Windows, same problem.

Here’s the compiler output:

Compiling group: haxe
cl.exe -Iinclude -nologo /WX- /fp:precise -DHX_WINDOWS -GR -O2(optim-std) -Zi(debug) -Fdc:\Users\Cambiata MusikProd\Downloads\haxe-cpp-basic-example\out\obj/msvc19xp/vc.pdb(debug) -Od(debug) -O2(release) -Os(optim-size) -FS -Oy- -c -EHs 
-GS- -arch:SSE2 -Ic:/Users/Cambiata MusikProd/Downloads/haxe-cpp-basic-example/.haxelib/hxcpp/4,2,1/include -DHXCPP_VISIT_ALLOCS(haxe) -DHX_SMART_STRINGS(haxe) -DHXCPP_API_LEVEL=400(haxe) -D_CRT_SECURE_NO_DEPRECATE -D_ALLOW_MSC_VER_MISMATCH -D_ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH -wd4996 ... tags=[haxe,static]
 - src/Main.cpp
Error: Main.cpp
./src/Main.cpp(32): error C2440: 'initializing': cannot convert from 'Greeter *' to 'Greeter'
./src/Main.cpp(32): note: No constructor could take the source type, or constructor overload resolution was ambiguous
./src/Main.cpp(33): error C2819: type 'Greeter' does not have an overloaded member 'operator ->'
c:/Users/Cambiata MusikProd/Downloads/haxe-cpp-basic-example/src/Greeter.cpp(3): note: see declaration of 'Greeter'
./src/Main.cpp(33): note: did you intend to use '.' instead?

I’m on Haxe 4.2.5 and hxcpp 4.2.1.

Ideas?

Hmm, just found that if I remove -D analyzer-optimize from the build.hxml file, it doesn’t work with anyone of the sayHello() or sayGoodbye() methods…

The root of your issue is that your create extern is returning a pointer (uses new) but the extern classes native metadata isn’t a pointer, i.e. you want @:extern("Greeter*"), not @:extern("Greeter").

As for why it partially works with the optimise flag thats because its optimising away the variable declaration when you only call a single one of its functions (new Greeter()->sayHello(); is generated). When you disable the optimiser or have two function calls the variable is actually generated and you run into the issue of your extern classes native metadata being wrong (cannot convert from 'Greeter *' to 'Greeter' hints at this).

Thank you, Aidan!

I’ve tried that too, and the strange thing is that it doesn’t make any difference at all in the generated Main.cpp

The Main.main() output looks the same either way (@:extern("Greeter*") or @:extern("Greeter"):

// from out/src/Main.cpp
...
void Main_obj::main(){
            	HX_STACKFRAME(&_hx_pos_e47a9afac0942eb9_2_main)
HXLINE(   3)		 ::Greeter greeter = (new Greeter());
HXLINE(   4)		greeter->sayHello();
HXLINE(   5)		greeter->sayGoodbye();
            	}

Very strange…

My code can be found at GitHub - cambiata/haxe-cpp-basic-example if that helps.

Ah, you’ve put @:extern instead of @:native on the extern class! Funnily enough I made that same mistake a few days ago… Once thats changed your example compiles fine for me.

Ah, thanks, Aidan! That did it!