hxcpp icon indicating copy to clipboard operation
hxcpp copied to clipboard

compilation error with nativeGen on interface

Open acarioni opened this issue 3 years ago • 7 comments

Environment macos monterey 12.1 haxe 4.2.4 hxcpp 4.2.1

The error can be reproduced by compiling the following two modules for the cpp target.

//LogManager.hx
package log;

@:nativeGen
interface Logger {
  function info(line: String): Void;
}

class LogManager {
  public static function getLogger(): Logger {
    return null;
  }
}
//Client.hx
package log;

class Client {
  static var logger = LogManager.getLogger();
}

The error reported is

Error: In file included from ./src/log/Client.cpp:1: In file included from /usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hxcpp.h:353: /usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/Dynamic.h:107:34: error: ambiguous conversion for functional-style cast from 'const Dynamic' to 'hx::Native<log::Logger *>' RETURN_ Cast() const { return RETURN_(*this); } ^~~~~~~~~~~~~ ./src/log/Client.cpp:53:55: note: in instantiation of function template specialization 'Dynamic::Cast<hx::Native<log::Logger >>' requested here if (HX_FIELD_EQ(inName,"logger") ) { logger=ioValue.Cast< ::hx::Native< log::Logger > >(); return true; } ^ /usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hx/Native.h:61:10: note: candidate constructor Native (const Native<T> &inNative) : ptr(inNative.ptr) { } ^ /usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hx/Native.h:63:10: note: candidate constructor Native (const cpp::Variant &inVariant) { ^ 1 error generated.

If the metadata @:nativeGen is removed from the interface Logger, the compilation works fine. But I need it because the interface is part of a library for which the end-users will provide a concrete implementation.

acarioni avatar Jan 14 '22 11:01 acarioni

Hello! Try to put @:unreflective meta on your Client class like:

//Client.hx
package log;

@:unreflective
class Client {
  static var logger = LogManager.getLogger();
}

posxposy avatar Jan 18 '22 14:01 posxposy

Thank you, now it works. But what is the meaning of the metadata? I can’t find any documentation about it.

acarioni avatar Jan 18 '22 14:01 acarioni

Nice to hear it works! It removes all that Dynamic stuff from your generated classes or methods. Basically, it removes reflection support. But maybe there are more hidden things under the hood, I'm not sure :)

posxposy avatar Jan 18 '22 15:01 posxposy

Unfortunately the trick of adding the metadata @:unreflective doesn’t seem to work in every circumstance. For example the following trivial code is not affected by it.

package foo;

@:nativeGen
interface IFoo {
  function foo(): Void;
}

class Main {
  static function getList(): Array<IFoo> {
    return [];
  }
}

The reported error is

haxelib run hxcpp Build.xml haxe -Dhaxe="4.2.4" -Dhaxe3="1" -Dhaxe4="1" -Dhaxe_ver="4.204" -Dhxcpp_api_level="400" -Dhxcpp_smart_strings="1" -Dsource_header="Generated by Haxe 4.2.4" -Dstatic="1" -Dtarget.name="cpp" -Dtarget.static="true" -Dtarget.sys="true" -Dtarget.threaded="true" -Dtarget.unicode="true" -Dtarget.utf16="true" -Dutf16="1" -I"" -I"/usr/local/lib/haxe/std/cpp/_std/" -I"/usr/local/lib/haxe/std/"
Creating /Users/foo/temp/bin/cpp/obj/darwin64/__pch/haxe/hxcpp.h.gch...

Compiling group: haxe
g++ -Iinclude -c -fvisibility=hidden -stdlib=libc++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk -O2 -I/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include -DHX_MACOS -m64 -Wno-parentheses -Wno-unused-value -Wno-format-extra-args -Wno-overflow -DHXCPP_M64 -DHXCPP_VISIT_ALLOCS(haxe) -DHX_SMART_STRINGS(haxe) -DHXCPP_API_LEVEL=400(haxe) ... tags=[haxe,static]
 - src/foo/Main.cpp 

Error: In file included from ./src/foo/Main.cpp:1:
In file included from /usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hxcpp.h:359:
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hx/Anon.h:236:42: error: no viable conversion from returned value of type 'hx::Native<foo::IFoo *>' to function return type 'hx::Val' (aka 'cpp::Variant')
      if (inField.__s==name1.__s) return t1;
                                         ^~
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hx/Anon.h:222:37: note: in instantiation of member function 'hx::AnonStruct2_obj<int, hx::Native<foo::IFoo *>>::__Field' requested here
      AnonStruct2_obj *result = new AnonStruct2_obj;
                                    ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hx/Operators.h:440:37: note: in instantiation of member function 'hx::AnonStruct2_obj<int, hx::Native<foo::IFoo *>>::Create' requested here
     hx::AnonStruct2_obj< int,TO >::Create(HX_("key",9f,89,51,00),p,
                                    ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/Array.h:103:4: note: in instantiation of member function 'hx::ArrayKeyValueIterator<hx::Native<foo::IFoo *>, hx::Native<foo::IFoo *>>::next' requested here
   ArrayKeyValueIterator(Array<FROM> inArray) : mArray(inArray), mIdx(0) { }
   ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/Array.h:856:44: note: in instantiation of member function 'hx::ArrayKeyValueIterator<hx::Native<foo::IFoo *>, hx::Native<foo::IFoo *>>::ArrayKeyValueIterator' requested here
   Dynamic keyValueIterator() { return new hx::ArrayKeyValueIterator<ELEM_,ELEM_>(this); }
                                           ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/Array.h:910:50: note: in instantiation of member function 'Array_obj<hx::Native<foo::IFoo *>>::keyValueIterator' requested here
   virtual Dynamic __keyValueIterator() { return keyValueIterator(); }
                                                 ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/Array.h:505:4: note: in instantiation of member function 'Array_obj<hx::Native<foo::IFoo *>>::__keyValueIterator' requested here
   Array_obj(int inSize,int inReserve) :
   ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/Array.h:1142:29: note: in instantiation of member function 'Array_obj<hx::Native<foo::IFoo *>>::Array_obj' requested here
 { return  Array<ELEM_>(new Array_obj(inSize,inReserve)); }
                            ^
./src/foo/Main.cpp:32:65: note: in instantiation of member function 'Array_obj<hx::Native<foo::IFoo *>>::__new' requested here
HXDLIN(  16)            return ::Array_obj< ::hx::Native< foo::IFoo* > >::__new(0);
                                                                          ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:21:11: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'const cpp::Variant &' for 1st argument
   struct Variant
          ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:21:11: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::Variant &&' for 1st argument
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:66:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'const null &' for 1st argument
      inline Variant(const null &) : type(typeObject), valObject(0) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:67:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'bool' for 1st argument
      inline Variant(bool inValue) : type(typeBool), valBool(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:68:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'double' for 1st argument
      inline Variant(double inValue) : type(typeDouble), valDouble(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:71:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::Int64' (aka 'long long') for 1st argument
      inline Variant(cpp::Int64 inValue) : type(typeInt64), valInt64(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:72:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::UInt64' (aka 'unsigned long long') for 1st argument
      inline Variant(cpp::UInt64 inValue) : type(typeInt64), valInt64(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:73:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'int' for 1st argument
      inline Variant(int inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:74:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::UInt32' (aka 'unsigned int') for 1st argument
      inline Variant(cpp::UInt32 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:75:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::Int16' (aka 'short') for 1st argument
      inline Variant(cpp::Int16 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:76:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::UInt16' (aka 'unsigned short') for 1st argument
      inline Variant(cpp::UInt16 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:77:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::Int8' (aka 'signed char') for 1st argument
      inline Variant(cpp::Int8 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:78:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::UInt8' (aka 'unsigned char') for 1st argument
      inline Variant(cpp::UInt8 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:89:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'hx::Object *' for 1st argument
      inline Variant(hx::Object *inValue) : type(typeObject), valObject(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:310:13: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'const ::String &' for 1st argument
   Variant::Variant(const ::String &inValue) :
            ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:313:13: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'const Dynamic &' for 1st argument
   Variant::Variant(const Dynamic &inRHS) : type(typeObject), valObject(inRHS.mPtr) { }
            ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:316:13: note: candidate template ignored: could not match 'ObjectPtr' against 'Native'
   Variant::Variant(const hx::ObjectPtr<SOURCE_> &inObjectPtr) :
            ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:92:23: note: explicit constructor is not a candidate
      explicit inline Variant(const cpp::Struct<T,H> &inVal);
                      ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:94:23: note: explicit constructor is not a candidate
      explicit inline Variant(const cpp::Pointer<T> &inRHS) ;
                      ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:96:23: note: explicit constructor is not a candidate
      explicit inline Variant(const cpp::Function<T> &inRHS) ;
                      ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:98:23: note: explicit constructor is not a candidate
      explicit inline Variant(const hx::Native<T> &inRHS) ;
                      ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hx/Native.h:76:17: note: candidate function
         inline operator T() const { return ptr; }
                ^
In file included from ./src/foo/Main.cpp:1:
In file included from /usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hxcpp.h:359:
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hx/Anon.h:244:48: error: no viable conversion from returned value of type 'hx::Native<foo::IFoo *>' to function return type 'hx::Val' (aka 'cpp::Variant')
      if (HX_QSTR_EQ_AE(inField,name1)) return t1;
                                               ^~
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:21:11: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'const cpp::Variant &' for 1st argument
   struct Variant
          ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:21:11: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::Variant &&' for 1st argument
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:66:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'const null &' for 1st argument
      inline Variant(const null &) : type(typeObject), valObject(0) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:67:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'bool' for 1st argument
      inline Variant(bool inValue) : type(typeBool), valBool(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:68:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'double' for 1st argument
      inline Variant(double inValue) : type(typeDouble), valDouble(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:71:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::Int64' (aka 'long long') for 1st argument
      inline Variant(cpp::Int64 inValue) : type(typeInt64), valInt64(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:72:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::UInt64' (aka 'unsigned long long') for 1st argument
      inline Variant(cpp::UInt64 inValue) : type(typeInt64), valInt64(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:73:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'int' for 1st argument
      inline Variant(int inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:74:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::UInt32' (aka 'unsigned int') for 1st argument
      inline Variant(cpp::UInt32 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:75:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::Int16' (aka 'short') for 1st argument
      inline Variant(cpp::Int16 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:76:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::UInt16' (aka 'unsigned short') for 1st argument
      inline Variant(cpp::UInt16 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:77:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::Int8' (aka 'signed char') for 1st argument
      inline Variant(cpp::Int8 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:78:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'cpp::UInt8' (aka 'unsigned char') for 1st argument
      inline Variant(cpp::UInt8 inValue) : type(typeInt), valInt(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:89:14: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'hx::Object *' for 1st argument
      inline Variant(hx::Object *inValue) : type(typeObject), valObject(inValue) { }
             ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:310:13: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'const ::String &' for 1st argument
   Variant::Variant(const ::String &inValue) :
            ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:313:13: note: candidate constructor not viable: no known conversion from 'hx::Native<foo::IFoo *>' to 'const Dynamic &' for 1st argument
   Variant::Variant(const Dynamic &inRHS) : type(typeObject), valObject(inRHS.mPtr) { }
            ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:316:13: note: candidate template ignored: could not match 'ObjectPtr' against 'Native'
   Variant::Variant(const hx::ObjectPtr<SOURCE_> &inObjectPtr) :
            ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:92:23: note: explicit constructor is not a candidate
      explicit inline Variant(const cpp::Struct<T,H> &inVal);
                      ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:94:23: note: explicit constructor is not a candidate
      explicit inline Variant(const cpp::Pointer<T> &inRHS) ;
                      ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:96:23: note: explicit constructor is not a candidate
      explicit inline Variant(const cpp::Function<T> &inRHS) ;
                      ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/cpp/Variant.h:98:23: note: explicit constructor is not a candidate
      explicit inline Variant(const hx::Native<T> &inRHS) ;
                      ^
/usr/local/Cellar/haxe/4.2.4/lib/haxe/lib/hxcpp/4,2,1/include/hx/Native.h:76:17: note: candidate function
         inline operator T() const { return ptr; }
                ^
2 errors generated.

acarioni avatar Jan 20 '22 10:01 acarioni

I assume that's because Haxe's Array<T> will work only with Haxe objects and will always be generated as ::Array< ::Dynamic>, so it can't cast IFoo to\from Dynamic type because IFoo is not really a Haxe object when you use @:nativeGen on it. As I know there was a way to write your own Dynamic containers, or something like that, for any custom type, but I don't know how to do it exactly, sorry. Probably you need to look into sources, maybe you will find something.

But as a workaround you could try to wrap your IFoo into something like this:

class FooWrapper {
    public final foo:IFoo;
    public function new(foo:IFoo) {
        this.foo = foo;
    }
}

So then you can use it in Haxe arrays as Array<FooWrapper>

posxposy avatar Jan 20 '22 11:01 posxposy

Thank you Dmitry. Your explanations are very useful.

acarioni avatar Jan 20 '22 13:01 acarioni

I'm not sure, but I remember haxe not allowing you to assign class level vars to null, it might also be why you're crashing - ita not an intended behavior

ShaharMS avatar Apr 26 '22 10:04 ShaharMS