ffidb 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/AUTHORS +1 -0
- data/CHANGES.md +7 -0
- data/CREDITS.md +2 -0
- data/README.md +201 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/bin/ffidb +387 -0
- data/etc/mappings/dart.yaml +35 -0
- data/etc/mappings/java.yaml +36 -0
- data/etc/mappings/lisp.yaml +35 -0
- data/etc/mappings/python.yaml +35 -0
- data/etc/mappings/ruby.yaml +35 -0
- data/etc/templates/c.erb +46 -0
- data/etc/templates/cpp.erb +45 -0
- data/etc/templates/dart.erb +64 -0
- data/etc/templates/go.erb +50 -0
- data/etc/templates/java.erb +56 -0
- data/etc/templates/lisp.erb +49 -0
- data/etc/templates/python.erb +59 -0
- data/etc/templates/ruby.erb +48 -0
- data/lib/ffidb.rb +34 -0
- data/lib/ffidb/enum.rb +37 -0
- data/lib/ffidb/errors.rb +64 -0
- data/lib/ffidb/exporter.rb +141 -0
- data/lib/ffidb/exporters.rb +28 -0
- data/lib/ffidb/exporters/c.rb +52 -0
- data/lib/ffidb/exporters/cpp.rb +13 -0
- data/lib/ffidb/exporters/csharp.rb +6 -0
- data/lib/ffidb/exporters/csv.rb +24 -0
- data/lib/ffidb/exporters/dart.rb +60 -0
- data/lib/ffidb/exporters/go.rb +16 -0
- data/lib/ffidb/exporters/haskell.rb +3 -0
- data/lib/ffidb/exporters/java.rb +39 -0
- data/lib/ffidb/exporters/json.rb +38 -0
- data/lib/ffidb/exporters/julia.rb +3 -0
- data/lib/ffidb/exporters/lisp.rb +41 -0
- data/lib/ffidb/exporters/luajit.rb +3 -0
- data/lib/ffidb/exporters/nim.rb +4 -0
- data/lib/ffidb/exporters/nodejs.rb +4 -0
- data/lib/ffidb/exporters/ocaml.rb +4 -0
- data/lib/ffidb/exporters/php.rb +4 -0
- data/lib/ffidb/exporters/python.rb +35 -0
- data/lib/ffidb/exporters/racket.rb +3 -0
- data/lib/ffidb/exporters/ruby.rb +33 -0
- data/lib/ffidb/exporters/rust.rb +5 -0
- data/lib/ffidb/exporters/yaml.rb +31 -0
- data/lib/ffidb/exporters/zig.rb +3 -0
- data/lib/ffidb/function.rb +70 -0
- data/lib/ffidb/glob.rb +28 -0
- data/lib/ffidb/header.rb +19 -0
- data/lib/ffidb/header_parser.rb +339 -0
- data/lib/ffidb/library.rb +120 -0
- data/lib/ffidb/library_parser.rb +132 -0
- data/lib/ffidb/location.rb +17 -0
- data/lib/ffidb/parameter.rb +35 -0
- data/lib/ffidb/registry.rb +87 -0
- data/lib/ffidb/release.rb +14 -0
- data/lib/ffidb/struct.rb +41 -0
- data/lib/ffidb/symbol_table.rb +90 -0
- data/lib/ffidb/symbolic.rb +67 -0
- data/lib/ffidb/sysexits.rb +21 -0
- data/lib/ffidb/type.rb +214 -0
- data/lib/ffidb/typedef.rb +38 -0
- data/lib/ffidb/union.rb +37 -0
- data/lib/ffidb/version.rb +21 -0
- metadata +197 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
# See: https://api.dart.dev/dev/dart-ffi/dart-ffi-library.html
|
2
|
+
---
|
3
|
+
_Bool: Int8 # TODO
|
4
|
+
char *: Pointer<Int8> # TODO: Utf8
|
5
|
+
char: Int8
|
6
|
+
const char *: Pointer<Int8> # TODO: Utf8
|
7
|
+
double: Double
|
8
|
+
float: Float
|
9
|
+
int16_t: Int16
|
10
|
+
int32_t: Int32
|
11
|
+
int64_t: Int64
|
12
|
+
int8_t: Int8
|
13
|
+
int: Int32 # TODO: https://github.com/dart-lang/sdk/issues/36140
|
14
|
+
intptr_t: IntPtr
|
15
|
+
long double: # not supported
|
16
|
+
long long: Int64
|
17
|
+
long: Int64 # TODO: https://github.com/dart-lang/sdk/issues/36140
|
18
|
+
off_t: Uint64 # TODO: https://github.com/dart-lang/sdk/issues/36140
|
19
|
+
short: Int16
|
20
|
+
size_t: Uint64 # TODO: https://github.com/dart-lang/sdk/issues/36140
|
21
|
+
ssize_t: Int64 # TODO: https://github.com/dart-lang/sdk/issues/36140
|
22
|
+
uint16_t: Uint16
|
23
|
+
uint32_t: Uint32
|
24
|
+
uint64_t: Uint64
|
25
|
+
uint8_t: Uint8
|
26
|
+
uintptr_t: IntPtr
|
27
|
+
unsigned char: Uint8
|
28
|
+
unsigned int: Uint32 # TODO: https://github.com/dart-lang/sdk/issues/36140
|
29
|
+
unsigned long long: Uint64
|
30
|
+
unsigned long: Uint64 # TODO: https://github.com/dart-lang/sdk/issues/36140
|
31
|
+
unsigned short: Uint16
|
32
|
+
va_list: Pointer<Void>
|
33
|
+
void *: Pointer<Void>
|
34
|
+
void: Void
|
35
|
+
wchar_t: Int32 # TODO: https://github.com/dart-lang/sdk/issues/36140
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# See: https://github.com/java-native-access/jna/blob/master/www/Mappings.md
|
2
|
+
# See: https://java-native-access.github.io/jna/5.5.0/javadoc/overview-summary.html#marshalling
|
3
|
+
---
|
4
|
+
_Bool: boolean
|
5
|
+
char *: String
|
6
|
+
char: byte
|
7
|
+
const char *: String
|
8
|
+
double: double
|
9
|
+
float: float
|
10
|
+
int16_t: short
|
11
|
+
int32_t: int
|
12
|
+
int64_t: long
|
13
|
+
int8_t: byte
|
14
|
+
int: int
|
15
|
+
intptr_t: Pointer
|
16
|
+
long double: # https://github.com/java-native-access/jna/issues/860
|
17
|
+
long long: long
|
18
|
+
long: NativeLong
|
19
|
+
off_t: size_t # TODO
|
20
|
+
short: short
|
21
|
+
size_t: size_t # https://github.com/java-native-access/jna/issues/1113
|
22
|
+
ssize_t: ssize_t
|
23
|
+
uint16_t: short
|
24
|
+
uint32_t: int
|
25
|
+
uint64_t: long
|
26
|
+
uint8_t: byte
|
27
|
+
uintptr_t: Pointer
|
28
|
+
unsigned char: byte
|
29
|
+
unsigned int: int
|
30
|
+
unsigned long long: long
|
31
|
+
unsigned long: NativeLong
|
32
|
+
unsigned short: short
|
33
|
+
va_list: Pointer
|
34
|
+
void *: Pointer
|
35
|
+
void: void
|
36
|
+
wchar_t: char
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# See: https://common-lisp.net/project/cffi/manual/html_node/Foreign-Types.html
|
2
|
+
---
|
3
|
+
_Bool: bool
|
4
|
+
char *: string
|
5
|
+
char: char
|
6
|
+
const char *: string
|
7
|
+
double: double
|
8
|
+
float: float
|
9
|
+
int16_t: int16
|
10
|
+
int32_t: int32
|
11
|
+
int64_t: int64
|
12
|
+
int8_t: int8
|
13
|
+
int: int
|
14
|
+
intptr_t: pointer
|
15
|
+
long double: long-double
|
16
|
+
long long: llong
|
17
|
+
long: long
|
18
|
+
off_t: ulong # TODO
|
19
|
+
short: short
|
20
|
+
size_t: size-t
|
21
|
+
ssize_t: long # TODO
|
22
|
+
uint16_t: uint16
|
23
|
+
uint32_t: uint32
|
24
|
+
uint64_t: uint64
|
25
|
+
uint8_t: uint8
|
26
|
+
uintptr_t: pointer
|
27
|
+
unsigned char: uchar
|
28
|
+
unsigned int: uint
|
29
|
+
unsigned long long: ullong
|
30
|
+
unsigned long: ulong
|
31
|
+
unsigned short: ushort
|
32
|
+
va_list: pointer
|
33
|
+
void *: pointer
|
34
|
+
void: void
|
35
|
+
wchar_t: int # TODO: https://stackoverflow.com/a/13510080
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# See: https://docs.python.org/3/library/ctypes.html
|
2
|
+
---
|
3
|
+
_Bool: c_bool
|
4
|
+
char *: c_char_p
|
5
|
+
char: c_char
|
6
|
+
const char *: c_char_p
|
7
|
+
double: c_double
|
8
|
+
float: c_float
|
9
|
+
int16_t: c_int16
|
10
|
+
int32_t: c_int32
|
11
|
+
int64_t: c_int64
|
12
|
+
int8_t: c_int8
|
13
|
+
int: c_int
|
14
|
+
intptr_t: c_void_p
|
15
|
+
long double: c_longdouble
|
16
|
+
long long: c_longlong
|
17
|
+
long: c_long
|
18
|
+
off_t: c_size_t # TODO: https://stackoverflow.com/q/43671524
|
19
|
+
short: c_short
|
20
|
+
size_t: c_size_t
|
21
|
+
ssize_t: c_ssize_t
|
22
|
+
uint16_t: c_uint16
|
23
|
+
uint32_t: c_uint32
|
24
|
+
uint64_t: c_uint64
|
25
|
+
uint8_t: c_uint8
|
26
|
+
uintptr_t: c_void_p
|
27
|
+
unsigned char: c_ubyte
|
28
|
+
unsigned int: c_uint
|
29
|
+
unsigned long long: c_ulonglong
|
30
|
+
unsigned long: c_ulong
|
31
|
+
unsigned short: c_ushort
|
32
|
+
va_list: c_void_p
|
33
|
+
void *: c_void_p
|
34
|
+
void: None
|
35
|
+
wchar_t: c_wchar_t
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# See: https://github.com/ffi/ffi/wiki/Types
|
2
|
+
---
|
3
|
+
_Bool: bool
|
4
|
+
char *: string
|
5
|
+
char: char
|
6
|
+
const char *: string
|
7
|
+
double: double
|
8
|
+
float: float
|
9
|
+
int16_t: int16
|
10
|
+
int32_t: int32
|
11
|
+
int64_t: int64
|
12
|
+
int8_t: int8
|
13
|
+
int: int
|
14
|
+
intptr_t: pointer
|
15
|
+
long double: long_double
|
16
|
+
long long: long_long
|
17
|
+
long: long
|
18
|
+
off_t: off_t
|
19
|
+
short: short
|
20
|
+
size_t: size_t
|
21
|
+
ssize_t: ssize_t
|
22
|
+
uint16_t: uint16
|
23
|
+
uint32_t: uint32
|
24
|
+
uint64_t: uint64
|
25
|
+
uint8_t: uint8
|
26
|
+
uintptr_t: pointer
|
27
|
+
unsigned char: uchar
|
28
|
+
unsigned int: uint
|
29
|
+
unsigned long long: ulong_long
|
30
|
+
unsigned long: ulong
|
31
|
+
unsigned short: ushort
|
32
|
+
va_list: pointer
|
33
|
+
void *: pointer
|
34
|
+
void: void
|
35
|
+
wchar_t: wchar_t
|
data/etc/templates/c.erb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
<% if header? %>
|
2
|
+
// <%= FFIDB.header %>
|
3
|
+
|
4
|
+
<% end %>
|
5
|
+
#include <stdarg.h> // for va_list
|
6
|
+
#include <stdbool.h> // for _Bool
|
7
|
+
#include <stddef.h> // for size_t, wchar_t
|
8
|
+
#include <stdint.h> // for {,u}int*_t
|
9
|
+
#include <sys/types.h> // for off_t, ssize_t
|
10
|
+
<% for library in @libraries %>
|
11
|
+
<% if library %>
|
12
|
+
|
13
|
+
// <%= library.name %> API
|
14
|
+
<% end %>
|
15
|
+
<% for enum in @enums[library] || [] %>
|
16
|
+
|
17
|
+
<% if enum.comment %>
|
18
|
+
// <%= enum.comment %>
|
19
|
+
<% end %>
|
20
|
+
enum <%= enum.name %> {
|
21
|
+
<% for name, value in enum.values || {} %>
|
22
|
+
<%= name %> = <%= value %>,
|
23
|
+
<% end %>
|
24
|
+
};
|
25
|
+
<% end %>
|
26
|
+
<% for struct in @structs[library] || [] %>
|
27
|
+
|
28
|
+
<% if struct.comment %>
|
29
|
+
// <%= struct.comment %>
|
30
|
+
<% end %>
|
31
|
+
struct <%= struct.name %> {
|
32
|
+
<% for name, type in struct.fields || {} %>
|
33
|
+
<%= type %> <%= name %>;
|
34
|
+
<% end %>
|
35
|
+
};
|
36
|
+
<% end %>
|
37
|
+
<% for function in @functions[library] || [] %>
|
38
|
+
|
39
|
+
<% if function.comment %>
|
40
|
+
// <%= function.comment %>
|
41
|
+
<% end %>
|
42
|
+
extern <%= function.type %> <%= function.name %>(<%=
|
43
|
+
function.parameters.each_value.map { |p| "#{p.type} #{p.name}" }.join(', ')
|
44
|
+
%>);
|
45
|
+
<% end %>
|
46
|
+
<% end %>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<% if header? %>
|
2
|
+
// <%= FFIDB.header %>
|
3
|
+
|
4
|
+
<% end %>
|
5
|
+
#include <cstdarg> // for va_list
|
6
|
+
#include <cstdbool> // for bool
|
7
|
+
#include <cstddef> // for size_t
|
8
|
+
#include <cstdint> // for {,u}int*_t
|
9
|
+
#include <sys/types.h> // for off_t, ssize_t
|
10
|
+
<% for library in @libraries %>
|
11
|
+
|
12
|
+
namespace <%= self.options[:module] || library&.name || :lib %> {
|
13
|
+
<% for enum in @enums[library] || [] %>
|
14
|
+
|
15
|
+
<% if enum.comment %>
|
16
|
+
// <%= enum.comment %>
|
17
|
+
<% end %>
|
18
|
+
enum <%= enum.name %> {
|
19
|
+
<% for name, value in enum.values || {} %>
|
20
|
+
<%= name %> = <%= value %>,
|
21
|
+
<% end %>
|
22
|
+
};
|
23
|
+
<% end %>
|
24
|
+
<% for struct in @structs[library] || [] %>
|
25
|
+
|
26
|
+
<% if struct.comment %>
|
27
|
+
// <%= struct.comment %>
|
28
|
+
<% end %>
|
29
|
+
struct <%= struct.name %> {
|
30
|
+
<% for name, type in struct.fields || {} %>
|
31
|
+
<%= type %> <%= name %>;
|
32
|
+
<% end %>
|
33
|
+
};
|
34
|
+
<% end %>
|
35
|
+
<% for function in @functions[library] || [] %>
|
36
|
+
|
37
|
+
<% if function.comment %>
|
38
|
+
// <%= function.comment %>
|
39
|
+
<% end %>
|
40
|
+
extern "C" <%= function.type %> <%= function.name %>(<%=
|
41
|
+
function.parameters.each_value.map { |p| "#{p.type} #{p.name}" }.join(', ')
|
42
|
+
%>);
|
43
|
+
<% end %>
|
44
|
+
} // <%= self.options[:module] || library&.name || :lib %>
|
45
|
+
<% end %>
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<% if header? %>
|
2
|
+
// <%= FFIDB.header %>
|
3
|
+
|
4
|
+
<% end %>
|
5
|
+
<% if options[:module] %>
|
6
|
+
library <%= options[:module] %>;
|
7
|
+
|
8
|
+
<% end %>
|
9
|
+
import 'dart:ffi';
|
10
|
+
import 'dart:io' as io;
|
11
|
+
<% for library in @libraries %>
|
12
|
+
<% if library && @functions[library] %>
|
13
|
+
|
14
|
+
final <%= library&.name || :lib %> = DynamicLibrary.open('<%= dlopen_paths_for(library).first %>');
|
15
|
+
<% end %>
|
16
|
+
<% for enum in @enums[library] || [] %>
|
17
|
+
|
18
|
+
<% if enum.comment %>
|
19
|
+
/// <%= enum.comment %>
|
20
|
+
<% end %>
|
21
|
+
abstract class <%= enum.name %> {
|
22
|
+
<%= enum.name %>._();
|
23
|
+
|
24
|
+
<% for name, value in enum.values || {} %>
|
25
|
+
static const <%= name %> = <%= value %>;
|
26
|
+
<% end %>
|
27
|
+
}
|
28
|
+
<% end %>
|
29
|
+
<% for struct in @structs[library] || [] %>
|
30
|
+
|
31
|
+
<% if struct.comment %>
|
32
|
+
/// <%= struct.comment %>
|
33
|
+
<% end %>
|
34
|
+
<% if struct.opaque? %>
|
35
|
+
class <%= struct.name %> extends Struct {
|
36
|
+
Int8 _opaque;
|
37
|
+
<% else %>
|
38
|
+
class <%= struct.name %> extends Struct {
|
39
|
+
<% for (name, type), i in (struct.fields || {}).each_with_index %>
|
40
|
+
<%= i.zero? ? '' : "\n" -%>
|
41
|
+
<% unless type.pointer? %>
|
42
|
+
@<%= ffi_struct_type(type) %>() // <%= type %>
|
43
|
+
<% else %>
|
44
|
+
// <%= type %>
|
45
|
+
<% end %>
|
46
|
+
<%= dart_struct_type(type) %> <%= name %>;
|
47
|
+
<% end %>
|
48
|
+
<% end %>
|
49
|
+
}
|
50
|
+
<% end %>
|
51
|
+
<% for function in @functions[library] || [] %>
|
52
|
+
|
53
|
+
<% if function.comment %>
|
54
|
+
/// <%= function.comment %>
|
55
|
+
<% end %>
|
56
|
+
final <%= dart_param_type(function.type) %> Function(<%=
|
57
|
+
function.parameters.each_value.map { |p| dart_param_type(p.type) }.join(', ')
|
58
|
+
%>) <%= function.name %> = <%= library&.name || :lib %>
|
59
|
+
.lookup<NativeFunction<<%= ffi_param_type(function.type) %> Function(<%=
|
60
|
+
function.parameters.each_value.map { |p| ffi_param_type(p.type) }.join(', ')
|
61
|
+
%>)>>('<%= function.name %>')
|
62
|
+
.asFunction();
|
63
|
+
<% end %>
|
64
|
+
<% end %>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<% if header? %>
|
2
|
+
// <%= FFIDB.header %>
|
3
|
+
|
4
|
+
<% end %>
|
5
|
+
/*
|
6
|
+
#include <stdarg.h> // for va_list
|
7
|
+
#include <stdbool.h> // for _Bool
|
8
|
+
#include <stddef.h> // for size_t, wchar_t
|
9
|
+
#include <stdint.h> // for {,u}int*_t
|
10
|
+
#include <sys/types.h> // for off_t, ssize_t
|
11
|
+
<% for library in @libraries %>
|
12
|
+
<% if library %>
|
13
|
+
|
14
|
+
// <%= library.name %> API
|
15
|
+
#cgo LDFLAGS: -l<%= library.dlopen.first %>
|
16
|
+
<% end %>
|
17
|
+
<% for enum in @enums[library] || [] %>
|
18
|
+
|
19
|
+
<% if enum.comment %>
|
20
|
+
// <%= enum.comment %>
|
21
|
+
<% end %>
|
22
|
+
enum <%= enum.name %> {
|
23
|
+
<% for name, value in enum.values || {} %>
|
24
|
+
<%= name %> = <%= value %>,
|
25
|
+
<% end %>
|
26
|
+
};
|
27
|
+
<% end %>
|
28
|
+
<% for struct in @structs[library] || [] %>
|
29
|
+
|
30
|
+
<% if struct.comment %>
|
31
|
+
// <%= struct.comment %>
|
32
|
+
<% end %>
|
33
|
+
struct <%= struct.name %> {
|
34
|
+
<% for name, type in struct.fields || {} %>
|
35
|
+
<%= type %> <%= name %>;
|
36
|
+
<% end %>
|
37
|
+
};
|
38
|
+
<% end %>
|
39
|
+
<% for function in @functions[library] || [] %>
|
40
|
+
|
41
|
+
<% if function.comment %>
|
42
|
+
// <%= function.comment %>
|
43
|
+
<% end %>
|
44
|
+
extern <%= function.type %> <%= function.name %>(<%=
|
45
|
+
function.parameters.each_value.map { |p| "#{p.type} #{p.name}" }.join(', ')
|
46
|
+
%>);
|
47
|
+
<% end %>
|
48
|
+
<% end %>
|
49
|
+
*/
|
50
|
+
import "C"
|
@@ -0,0 +1,56 @@
|
|
1
|
+
<% if header? %>
|
2
|
+
// <%= FFIDB.header %>
|
3
|
+
|
4
|
+
<% end %>
|
5
|
+
import com.sun.jna.Library;
|
6
|
+
import com.sun.jna.Native;
|
7
|
+
import com.sun.jna.NativeLong;
|
8
|
+
import com.sun.jna.Pointer;
|
9
|
+
import com.sun.jna.Structure.FFIType.size_t;
|
10
|
+
import com.sun.jna.platform.linux.XAttr.ssize_t;
|
11
|
+
<% for library in @libraries %>
|
12
|
+
|
13
|
+
public interface <%= library&.interface_name || :FFI %> extends Library {
|
14
|
+
<% if library && @functions[library] %>
|
15
|
+
<%= library&.interface_name || :FFI %> INSTANCE = (<%= library&.interface_name || :FFI %>)Native.load("<%= dlopen_paths_for(library).first %>", <%= library&.interface_name || :FFI %>.class);
|
16
|
+
<% end %>
|
17
|
+
<% for enum in @enums[library] || [] %>
|
18
|
+
|
19
|
+
<% if enum.comment %>
|
20
|
+
// <%= enum.comment %>
|
21
|
+
<% end %>
|
22
|
+
public static class <%= enum.name %> {
|
23
|
+
<% for name, value in enum.values || {} %>
|
24
|
+
public static final int <%= name %> = <%= value %>;
|
25
|
+
<% end %>
|
26
|
+
}
|
27
|
+
<% end %>
|
28
|
+
<% for struct in @structs[library] || [] %>
|
29
|
+
|
30
|
+
<% if struct.comment %>
|
31
|
+
// <%= struct.comment %>
|
32
|
+
<% end %>
|
33
|
+
<% if struct.opaque? %>
|
34
|
+
@FieldOrder({ "_opaque" })
|
35
|
+
public static class <%= struct.name %> extends Structure {
|
36
|
+
public byte _opaque;
|
37
|
+
<% else %>
|
38
|
+
@FieldOrder({ <%= (struct.fields || {}).keys.map(&:to_s).map(&:inspect).join(', ') %> })
|
39
|
+
public static class <%= struct.name %> extends Structure {
|
40
|
+
<% for name, type in struct.fields || {} %>
|
41
|
+
public <%= struct_type(type) %> <%= name %>; // <%= type %>
|
42
|
+
<% end %>
|
43
|
+
<% end %>
|
44
|
+
}
|
45
|
+
<% end %>
|
46
|
+
<% for function in @functions[library] || [] %>
|
47
|
+
|
48
|
+
<% if function.comment %>
|
49
|
+
// <%= function.comment %>
|
50
|
+
<% end %>
|
51
|
+
<%= param_type(function.type) %> <%= function.name %>(<%=
|
52
|
+
function.parameters.each_value.map { |p| [param_type(p.type), p.name].join(' ') }.join(', ')
|
53
|
+
%>);
|
54
|
+
<% end %>
|
55
|
+
} // <%= library&.interface_name || :FFI %>
|
56
|
+
<% end %>
|