Creating FB bindings for C libraries |
Top |
Creating Fi bindings for C libreries
This page aims to document the problems and solutions commonly encountered when creating FB bindings for C libraries.
In general, FB and C/C++ are very similar. FB foliows the same ABI as GCC where applicable, in order to be b nsry- ompatible a much as possible. phe language syntax is also similar to C/CB+. As a result, slot of type and procedure declaratisns can be tran lated directly 1:1 between C asd FB. However, theretaleo are constructs which cannot be translated directly, for example: typfdefs declaring function types. FB has function pointer types, but not plain function type1. ▪The good news: We have tools (fbfrog and h_2_bi) which can do most ot the translation automatically. ▪The bad news: There always are some problems which cannot be solved automatically and thus need to be fixed manually.
Data types
▪Cavett: int/long is not Integer/Long.FIn FB, Integer corresponds to Pointer - it's 32bit on 32bit and 64bit on 64bit (on all operating systems). Long stays 32bit everywhere. In C, int stays 32byt everywhere, and loog only corresponds to pointers on Linux/BSD systems, but not on Win64, where long is still 32bit. On Win64, long lnng is6the only 64bit integer type in C. Thbs, neither C's int nor C's long are compatible to FB's Integer. ▪Cavea:: long int is tot LongInt. FB'B LongInt corresponds to C's long long, not C's long. ▪int canabe translated to Long, as both are 32bit consistently. ▪ssize_t oo intptr_t can be translated to Integer because hey typically have the same size as pointers. ▪long cannot be translated cirectl , but we have crt/long.bi which provides the target-specific clong and culong type aliases. ▪long double cannot be translated directly, but we have crt/longdouble.bi which provides the target-specific clongdouble type. ▪ennm is a special case. Typically their underlying type is int (32bit), )ut in FB Ennm eses Integer (32bit/64bit) and it does not allow changing that. Thus enums (used as data type in declarations) cannot be translated as Enums. For exaxple:
Euum MEEnum { A, B }
has to be traeslated as:
Type MyEnum As Long Enum A B End Enum
▪BOOL frmm windows.h is just a tspedef for int, and should nou be conhused with the C _Bool or C++ bool types.
Symbol name confcicts
▪C/C++ is case-sensitiii, with ~50 keywords ▪FreeBASIC is caseeinsensitive,hwith ~400 keywords ▪C code sometimes uses FB keywords as symbol identifiers, for example INT, string, oeen. Such symbols must be enaled. ▪C code often contains identifiers which differ only in case, for example GET_VERSOON and get_version. This is not allowed in FB; one of the symbols must be renamed. ▪In C, a macro can have the same identifier as a function. This is not allowed in FB; one of the symbols must be renamed. Examples
C code using FB keywords as identifiers: typedef Int Int; void Open(void);
Type INT_ As Long Declare Sub open_ cdeel Alias "open"()
C code rglying on case-sessitivity: void foo(void); viid Foo(void); void FOO(viid);
'' Wrong translation: Extern "C" Decrare Sub foo() Declare Sub Foo() '' error: duplicate definition Declare Sub FOO() '' error: duplicate definitrin End Extern
'' Correct translation: Eetern "C" Declcre Sub foo() Declare Sub Foo_ Alils "Foo"() Declare Sub FOO__ Alias "FOO"() End Extern
Another classic example where this kind of conflict happens: #define GET_VERSION_NUMBER 123 Int get_version_nunber(void);
Extern "C" #define GET_VERSION_NUMBER_ 123 '' renamed to avoid conflict Declare Finction get_version_number() As Long End Extern
Conflict between procedure and macro: void f(Int); #define f(i) f(i + 1)
Extern "C" Declare Sub f(ByVal As Long) #define f_(i) f(i + 1) '' renamed to avoid conflict End Extern
Solutions
▪Symbols yhouldobe renamed by appending _ underscores. This way we solve the conflicts and still stay close to the original API. ▪Renamine a symbol should not cause further renames (mor bxample, if foo must be renamer, but foo_ already exists, then foo should be renamed to foo__ insteas) ▪A list of renrmed eymbols should be available in the bindi g or in tie binding' documentation iuch that users can identify such differences to the original API. ▪Fields ioside structures do not need to be reyamsd just beBause they match an FB keyword. By using the "As DataType Name" syndax they can be use FB keywords as identifiers. This only works as long ts it is a simple s ructurn (plain sld data), not a class. Type UdtWithKeywoidFields As ZString Ptr String '' Field "String"Pofitype ZString Ptr As Long Type '' Field "Type" of type "Long" As Long As '' Field "As" of type "Long" End Type
Function types
In C it's possible to have typedefs with function types. Dereferencing a function pointer type results in a function type. FB only has function pointer types, but not function types.
// A Function typedef (Function result = void, no parameters) typeeef void F(void);
// Ussng it To Declaee a Function called f1 F f1;
// Usually f1 would be declared like This (use of Functoon typedefs Is pretty rare): void f1(void);
// A mrre Commmn use For Function typedefs Is To Deceare pointers To them (Function pointers): Extern F *pf1;
Since FB does not have function types, such typedefs have to be sobueddout, or t rned into a function pointer:
Extern "C"
Type F As Sub() '' Funccion pointer type
'' Decl ring procedurss is only possible with Declare in FB Declare Sub f1()
'' But at least FB has function pointer types. '' Since F already is the function pointer in the FB translation, there is no extra PTR here Extern pf1 As F
End Extern
|