Aurel300/ammer

Building in Wrong Order

Closed this issue · 6 comments

It loooks like Ammer is building in the wrong order; I'm not 100% sure what the build process is for Ammer, but I assume it generally is supposed to "build out" the Library<T> type (in its entirety) first before attempting to build the Library's derived Pointer types.

However, with this code:

import ammer.*;
import ammer.ffi.*;
import haxe.io.Bytes;
// @:ammer.nativePrefix("odbc_")
class Odbc extends Library<"odbc"> {
  public static function odbc_connect(cnxStr:String):OdbcCtx;
    // public static function test_sql():Int;
}
// @:ammer.nativePrefix("odbc_")
class OdbcCtx extends Pointer<"odbc_ctx_t", Odbc> {
  public function odbc_execute(_:ammer.ffi.This, query:String):OdbcStmtCtx;
  public  function odbc_disconnect(_:ammer.ffi.This):Bool;
  public function odbc_get_ctx_errors(_:ammer.ffi.This):String;
}
// @:ammer.nativePrefix("odbc_")
class OdbcStmtCtx extends Pointer<"odbc_stmt_t", Odbc> {
    public function odbc_get_stmt_errors(_:ammer.ffi.This):String;
    public function odbc_get_column_name(_:ammer.ffi.This, i:Int):String;
    public function odbc_get_column_datatype(_:ammer.ffi.This, i:Int):Int;
    public function odbc_get_column_size(_:ammer.ffi.This, i:Int):UInt;
    public function odbc_get_column_decimal_digits(_:ammer.ffi.This, i:Int):Int;
    public function odbc_get_column_nullable(_:ammer.ffi.This, i:Int):Int;
}

OdbcStmtCtx doesn't build because for some reason the compiler is trying to find its fields in the Odbc Library class, see the error:

Odbc.hx:17: characters 5-67 : Class<Odbc> has no field odbc_get_stmt_errors (Suggestion: odbc_get_ctx_errors)
Odbc.hx:18: characters 5-74 : Class<Odbc> has no field odbc_get_column_name
Odbc.hx:19: characters 5-75 : Class<Odbc> has no field odbc_get_column_datatype
Odbc.hx:20: characters 5-72 : Class<Odbc> has no field odbc_get_column_size
Odbc.hx:21: characters 5-81 : Class<Odbc> has no field odbc_get_column_decimal_digits
Odbc.hx:22: characters 5-75 : Class<Odbc> has no field odbc_get_column_nullable

I assume what happens is static methods get created on the library method which are then called in the Pointer instance methods, for whatever reason, the Library static methods for OdbcStmtCtx aren't being built before Ammer attempts to build OdbcStmtCtx's Pointer type.

When I forcefully inject the methods into the Library type like so:

class Odbc extends Library<"odbc"> {
  public static function odbc_connect(cnxStr:String):OdbcCtx;
  public static function odbc_get_stmt_errors(ptr:OdbcStmtCtx):String;
    public static function odbc_get_column_name(ptr:OdbcStmtCtx, i:Int):String;
    public static function odbc_get_column_datatype(ptr:OdbcStmtCtx, i:Int):Int;
    public static function odbc_get_column_size(ptr:OdbcStmtCtx, i:Int):UInt;
    public static function odbc_get_column_decimal_digits(ptr:OdbcStmtCtx, i:Int):Int;
public function odbc_get_column_nullable(ptr:OdbcStmtCtx, i:Int):Int;
    // public static function test_sql():Int;
}

It builds (or at least gets further in the build process) and then errors out:

Odbc.hx:23: characters 5-67 : Duplicate class field declaration : Odbc.odbc_get_stmt_errors
Odbc.hx:5: lines 5-14 : Defined in this class
Odbc.hx:24: characters 5-74 : Duplicate class field declaration : Odbc.odbc_get_column_name
Odbc.hx:5: lines 5-14 : Defined in this class
Odbc.hx:25: characters 5-75 : Duplicate class field declaration : Odbc.odbc_get_column_datatype
Odbc.hx:5: lines 5-14 : Defined in this class
Odbc.hx:26: characters 5-72 : Duplicate class field declaration : Odbc.odbc_get_column_size
Odbc.hx:5: lines 5-14 : Defined in this class
Odbc.hx:27: characters 5-81 : Duplicate class field declaration : Odbc.odbc_get_column_decimal_digits
Odbc.hx:5: lines 5-14 : Defined in this class
Odbc.hx:28: characters 5-75 : Same field name can't be used for both static and instance : odbc_get_column_nullable
Odbc.hx:5: lines 5-14 : Defined in this class

Which to me seems to indicate that the static library fields do indeed get added, just not soon enough in the build process.

Actually it's not a problem with wrong order.
As i know, stuck with the same problem, Ammer process Pointers that referenced in the Library.
You can use temporary fix - move one method like odbc_get_stmt_errors from OdbcStmtCtx to Odbc.

Thanks for the report. Pointers are a bit messy. Because the methods of all pointers end up in the class generated by the library definition, all pointer types need to "register" with their library before the fields of the library are actually generated (I cannot add more fields to a finished type at an arbitrary time). This works for the tests, but I think your use case has a slightly more complex situation – the second pointer type OdbcStmtCtx is only linked by the return type of a method in the first pointer type OdbcCtx. So it seems that pointer types that are themselves linked by methods added from pointer types are not scanned properly.

Thanks for the report. Pointers are a bit messy. Because the methods of all pointers end up in the class generated by the library definition, all pointer types need to "register" with their library before the fields of the library are actually generated (I cannot add more fields to a finished type at an arbitrary time). This works for the tests, but I think your use case has a slightly more complex situation – the second pointer type OdbcStmtCtx is only linked by the return type of a method in the first pointer type OdbcCtx. So it seems that pointer types that are themselves linked by methods added from pointer types are not scanned properly.

So is the actual fix to add a ghost method that returns a odbc_stmt_ptr/OdbcStmtCtx?

No, that is just a workaround. I think this might be a relatively quick fix on my side.

No, that is just a workaround. I think this might be a relatively quick fix on my side.

Yeah, that's what I meant.

The workaround works btw:

import ammer.*;
import ammer.ffi.*;
import haxe.io.Bytes;
@:ammer.nativePrefix("odbc_")
class Odbc extends Library<"odbc"> {
  public static function connect(cnxStr:String):OdbcCtx;
  public static function stmt_reference():OdbcStmtCtx;
}

C++:

LIB_EXPORT odbc_stmt_ptr odbc_stmt_reference(void) {
	return (odbc_stmt_ptr)malloc(sizeof(odbc_stmt_ptr));
}

Sorry for the delay, it really was a tiny change. Let me know if this fixed your issue.