ffi.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2017 by Sven Barth
  4. member of the Free Pascal development team.
  5. Interface unit for the Foreign Function Interface library.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. }
  12. (* -------------------------------------------------------------------
  13. The basic API is described in the README file.
  14. The raw API is designed to bypass some of the argument packing
  15. and unpacking on architectures for which it can be avoided.
  16. The closure API allows interpreted functions to be packaged up
  17. inside a C function pointer, so that they can be called as C functions,
  18. with no understanding on the client side that they are interpreted.
  19. It can also be used in other cases in which it is necessary to package
  20. up a user specified parameter and a function pointer as a single
  21. function pointer.
  22. The closure API must be implemented in order to get its functionality,
  23. e.g. for use by gij. Routines are provided to emulate the raw API
  24. if the underlying platform doesn't allow faster implementation.
  25. More details on the raw and cloure API can be found in:
  26. http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
  27. and
  28. http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
  29. -------------------------------------------------------------------- *)
  30. unit ffi;
  31. interface
  32. uses
  33. ctypes;
  34. {
  35. from the various ffitarget.h
  36. }
  37. { ToDo: we need defines for the MIPS ABI }
  38. const
  39. {$if defined(CPUMIPS) or defined(CPU64)}
  40. FFI_SIZEOF_ARG = 8;
  41. {$else}
  42. FFI_SIZEOF_ARG = 4;
  43. {$endif}
  44. FFI_SIZEOF_JAVA_ARG = FFI_SIZEOF_ARG;
  45. {$if defined(CPUPOWERPC) and not defined(AIX) and not defined(DARWIN)}
  46. {$if defined(CPUPOWERPC32)}
  47. FFI_SYSV_SOFT_FLOAT = 1;
  48. FFI_SYSV_STRUCT_RET = 2;
  49. FFI_SYSV_IBM_LONG_DOUBLE = 4;
  50. FFI_SYSV_LONG_DOUBLE_128 = 16;
  51. {$elseif defined(CPUPOWERPC64)}
  52. FFI_LINUX_STRUCT_ALIGN = 1;
  53. FFI_LINUX_LONG_DOUBLE_128 = 2;
  54. {$endif}
  55. {$endif}
  56. type
  57. {$ifdef WIN64}
  58. ffi_arg = QWord;
  59. ffi_sarg = Int64;
  60. {$else}
  61. ffi_arg = culong;
  62. ffi_sarg = cslong;
  63. {$endif}
  64. ffi_abi = (
  65. {$if defined(CPUX86_64) and not defined(WIN64)}
  66. FFI_FIRST_ABI = 1,
  67. {$else}
  68. FFI_FIRST_ABI,
  69. {$endif}
  70. {$if not defined(CPUMIPS) and not defined(CPUX86_64) and not defined(CPUPOWERPC) and not defined(CPUSPARCGEN)}
  71. FFI_SYSV,
  72. {$endif}
  73. {$if defined(CPUARM)}
  74. FFI_VFP,
  75. {$endif}
  76. {$if defined(CPUMIPS)}
  77. FFI_O32,
  78. FFI_N32,
  79. FFI_N64,
  80. FFI_O32_SOFT_FLOAT,
  81. FFI_N32_SOFT_FLOAT,
  82. FFI_N64_SOFT_FLOAT,
  83. {$endif}
  84. {$if defined(CPUX86_64)}
  85. {$ifndef WIN64}
  86. FFI_UNIX64,
  87. {$endif}
  88. FFI_WIN64,
  89. FFI_GNUW64,
  90. {$endif}
  91. {$if defined(CPUI386)}
  92. {$ifdef WIN32}
  93. FFI_STDCALL,
  94. {$endif}
  95. FFI_THISCALL = 3,
  96. FFI_FASTCALL,
  97. {$ifdef WIN32}
  98. FFI_MS_CDECL,
  99. {$else}
  100. FFI_STDCALL,
  101. {$endif}
  102. FFI_PASCAL,
  103. FFI_REGISTER,
  104. {$ifndef WIN32}
  105. FFI_MS_CDECL,
  106. {$endif}
  107. {$endif}
  108. {$if defined(CPUSPARC32)}
  109. FFI_V8,
  110. {$endif}
  111. {$if defined(CPUSPARC64)}
  112. FFI_V9,
  113. {$endif}
  114. {$if defined(CPUPOWERPC)}
  115. { this one is getting ugly... }
  116. {$if defined(AIX) or defined(DARWIN)}
  117. FFI_AIX,
  118. FFI_DARWIN,
  119. {$else}
  120. FFI_COMPAT_SYSV,
  121. FFI_COMPAT_GCC_SYSV,
  122. FFI_COMPAT_LINUX64,
  123. FFI_COMPAT_LINUX,
  124. FFI_COMPAT_LINUX_SOFT_FLOAT,
  125. {$if defined(CPUPOWERPC64)}
  126. FFI_LINUX = 8,
  127. {$define NO_LAST_ABI}
  128. FFI_LAST_ABI = 12
  129. {$elseif defined(CPUPOWERPC32)}
  130. FFI_SYSV = 8,
  131. {$define NO_LAST_ABI}
  132. FFI_LAST_ABI = 32
  133. {$endif}
  134. {$endif}
  135. {$endif}
  136. {$ifndef NO_LAST_ABI}
  137. FFI_LAST_ABI
  138. {$endif}
  139. );
  140. { alias values }
  141. const
  142. {$if defined(CPUX86_64) and not defined(WIN64)}
  143. FFI_EFI64 = FFI_WIN64;
  144. {$endif}
  145. {$if defined(CPUARMHF)}
  146. FFI_DEFAULT_ABI = FFI_VFP;
  147. {$elseif defined(CPUMIPS)}
  148. { ToDo: needs define for ABI }
  149. FFI_DEFAULT_ABI = FFI_N32;
  150. {$elseif defined(CPUX86_64)}
  151. {$ifdef WIN64}
  152. FFI_DEFAULT_ABI = FFI_WIN64;
  153. {$else}
  154. FFI_DEFAULT_ABI = FFI_UNIX64;
  155. {$endif}
  156. {$elseif defined(CPUSPARC32)}
  157. FFI_DEFAULT_ABI = FFI_V8;
  158. {$elseif defined(CPUSPARC64)}
  159. FFI_DEFAULT_ABI = FFI_V9;
  160. {$elseif defined(CPUPOWERPC)}
  161. {$if defined(AIX)}
  162. FFI_DEFAULT_ABI = FFI_AIX;
  163. {$elseif defined(DARWIN)}
  164. FFI_DEFAULT_ABI = FFI_DARWIN;
  165. {$elseif defined(CPUPOWERPC64)}
  166. { ToDo: find out what needs to be set }
  167. FFI_DEFAULT_ABI = ffi_abi(Ord(FFI_LINUX) or FFI_LINUX_STRUCT_ALIGN or FFI_LINUX_LONG_DOUBLE_128);
  168. {$elseif defined(CPUPOWERPC)}
  169. { ToDo: find out what needs to be set }
  170. FFI_DEFAULT_ABI = ffi_abi(Ord(FFI_SYSV) {$ifdef FREEBSD}or FFI_SYSV_STRUCT_RET{$endif});
  171. {$endif}
  172. {$else}
  173. {$ifdef WIN32}
  174. FFI_DEFAULT_ABI = FFI_STDCALL;
  175. {$else}
  176. FFI_DEFAULT_ABI = FFI_SYSV;
  177. {$endif}
  178. {$endif}
  179. const
  180. {$if defined(CPUPOWERPC)}
  181. FFI_TARGET_HAS_COMPLEX_TYPE = False;
  182. {$else}
  183. FFI_TARGET_HAS_COMPLEX_TYPE = True;
  184. {$endif}
  185. (* ---- Definitions for closures ----------------------------------------- *)
  186. const
  187. FFI_CLOSURES = true;
  188. {$if defined(DARWIN) and (defined(CPUARM) or defined(CPUAARCH64))}
  189. FFI_EXEC_TRAMPOLINE_TABLE = True;
  190. {$else}
  191. FFI_EXEC_TRAMPOLINE_TABLE = False;
  192. {$endif}
  193. {$if defined(CPUI386)}
  194. FFI_NATIVE_RAW_API = True;
  195. {$else}
  196. FFI_NATIVE_RAW_API = False;
  197. {$endif}
  198. {$if defined(CPUARM) or defined(CPUX86_64) or defined(CPUI386) or defined(CPUSPARCGEN) or (defined(CPUAARCH64) and not defined(DARWIN)) or (defined(CPUPOWERPC) and not defined(DARWIN))}
  199. FFI_GO_CLOSURES = True;
  200. {$else}
  201. FFI_GO_CLOSURES = False;
  202. {$endif}
  203. {$if defined(CPUARM)}
  204. {$if defined(DARWIN)}
  205. FFI_TRAMPOLINE_SIZE = 12;
  206. FFI_TRAMPOLINE_CLOSURE_OFFSET = 8;
  207. {$elseif FFI_EXEC_TRAMPOLINE_TABLE}
  208. {$error 'No trampoline table implementation'}
  209. {$else}
  210. FFI_TRAMPOLINE_SIZE = 12;
  211. FFI_TRAMPOLINE_CLOSURE_OFFSET = FFI_TRAMPOLINE_SIZE;
  212. {$endif}
  213. {$elseif defined(CPUAARCH64)}
  214. {$if defined(DARWIN)}
  215. FFI_TRAMPOLINE_SIZE =16;
  216. FFI_TRAMPOLINE_CLOSURE_OFFSET = 16;
  217. {$elseif FFI_EXEC_TRAMPOLINE_TABLE}
  218. {$error 'No trampoline table implementation'}
  219. {$else}
  220. FFI_TRAMPOLINE_SIZE = 24;
  221. FFI_TRAMPOLINE_CLOSURE_OFFSET = FFI_TRAMPOLINE_SIZE;
  222. {$endif}
  223. {$elseif defined(CPUPOWERPC)}
  224. { ToDo: check for ELFv2? }
  225. {$ifdef ELF_V2}
  226. FFI_TRAMPOLINE_SIZE = 32;
  227. {$else}
  228. {$if defined(CPUPOWERPC64) or defined(AIX)}
  229. {$if defined(DARWIN)}
  230. FFI_TRAMPOLINE_SIZE = 48;
  231. {$else}
  232. FFI_TRAMPOLINE_SIZE = 25;
  233. {$endif}
  234. {$else}
  235. FFI_TRAMPOLINE_SIZE = 40;
  236. {$endif}
  237. {$endif}
  238. {$elseif defined(CPUSPARC32)}
  239. FFI_TRAMPOLINE_SIZE = 16;
  240. {$elseif defined(CPUSPARC64)}
  241. FFI_TRAMPOLINE_SIZE = 24;
  242. {$elseif defined(CPUX86_64)}
  243. FFI_TRAMPOLINE_SIZE = 24;
  244. {$elseif defined(CPUI386)}
  245. FFI_TRAMPOLINE_SIZE = 12;
  246. {$elseif defined(CPUM68K)}
  247. FFI_TRAMPOLINE_SIZE = 16;
  248. {$elseif defined(CPURISCV32)}
  249. FFI_TRAMPOLINE_SIZE = 24;
  250. {$elseif defined(CPURISCV64)}
  251. FFI_TRAMPOLINE_SIZE = 24;
  252. {$elseif defined(CPUMIPS32)}
  253. FFI_TRAMPOLINE_SIZE = 20;
  254. {$elseif defined(CPUMIPS64)}
  255. FFI_TRAMPOLINE_SIZE = 56;
  256. {$elseif defined(CPUXTENSA)}
  257. FFI_TRAMPOLINE_SIZE = 24;
  258. {$endif}
  259. {
  260. from ffi.h
  261. }
  262. const
  263. ffilibrary = 'ffi';
  264. {$if defined(CPUI8086) or defined(CPUI386) or (defined(CPUX86_64) and not defined(WIN64))}
  265. { Note: we can not use FPC_HAS_TYPE_EXTENDED here as libffi won't have the
  266. corresponding type no matter what }
  267. {$define HAVE_LONG_DOUBLE}
  268. {$endif}
  269. type
  270. pffi_type = ^ffi_type;
  271. ppffi_type = ^pffi_type;
  272. ffi_type = record
  273. size: csize_t;
  274. alignment: cushort;
  275. _type: cushort;
  276. elements: ppffi_type;
  277. end;
  278. var
  279. ffi_type_void: ffi_type; cvar; external ffilibrary;
  280. ffi_type_uint8: ffi_type; cvar; external ffilibrary;
  281. ffi_type_sint8: ffi_type; cvar; external ffilibrary;
  282. ffi_type_uint16: ffi_type; cvar; external ffilibrary;
  283. ffi_type_sint16: ffi_type; cvar; external ffilibrary;
  284. ffi_type_uint32: ffi_type; cvar; external ffilibrary;
  285. ffi_type_sint32: ffi_type; cvar; external ffilibrary;
  286. ffi_type_uint64: ffi_type; cvar; external ffilibrary;
  287. ffi_type_sint64: ffi_type; cvar; external ffilibrary;
  288. ffi_type_float: ffi_type; cvar; external ffilibrary;
  289. ffi_type_double: ffi_type; cvar; external ffilibrary;
  290. ffi_type_pointer: ffi_type; cvar; external ffilibrary;
  291. {$ifdef HAVE_LONG_DOUBLE}
  292. ffi_type_longdouble: ffi_type; cvar; external ffilibrary;
  293. {$else}
  294. ffi_type_longdouble: ffi_type absolute ffi_type_double;
  295. {$endif}
  296. {$if FFI_TARGET_HAS_COMPLEX_TYPE}
  297. ffi_type_complex_single: ffi_type; cvar; external ffilibrary;
  298. ffi_type_complex_double: ffi_type; cvar; external ffilibrary;
  299. {$ifdef HAVE_LONG_DOUBLE}
  300. ffi_type_complex_longdouble: ffi_type; cvar; external ffilibrary;
  301. {$endif}
  302. {$endif}
  303. { type aliases }
  304. ffi_type_uchar: ffi_type absolute ffi_type_uint8;
  305. ffi_type_schar: ffi_type absolute ffi_type_sint8;
  306. { ToDo: check when C's short isn't 2 byte }
  307. ffi_type_ushort: ffi_type absolute ffi_type_uint16;
  308. ffi_type_sshort: ffi_type absolute ffi_type_sint16;
  309. { ToDo: check when C's int isn't 4 byte }
  310. ffi_type_uint: ffi_type absolute ffi_type_uint32;
  311. ffi_type_sint: ffi_type absolute ffi_type_sint32;
  312. {$if defined(CPU64) and not defined(WIN64)}
  313. ffi_type_ulong: ffi_type absolute ffi_type_uint64;
  314. ffi_type_slong: ffi_type absolute ffi_type_sint64;
  315. {$else}
  316. ffi_type_ulong: ffi_type absolute ffi_type_uint32;
  317. ffi_type_slong: ffi_type absolute ffi_type_sint32;
  318. {$endif}
  319. type
  320. ffi_status = (
  321. FFI_OK,
  322. FFI_BAD_TYPEDEF,
  323. FFI_BAD_ABI
  324. );
  325. pffi_cif = ^ffi_cif;
  326. ffi_cif = record
  327. abi: ffi_abi;
  328. nargs: cunsigned;
  329. arg_type: ppffi_type;
  330. rtype: pffi_type;
  331. bytes: cunsigned;
  332. flags: cunsigned;
  333. {$if defined(CPUARM)}
  334. vfp_used: cint;
  335. vfp_reg_free: cushort;
  336. vfp_nargs: cushort;
  337. vfp_args: array[0..15] of cchar;
  338. {$elseif defined(CPUAARCH64)}
  339. {$ifdef DARWIN}
  340. aarch64_nfixedargs: cuint;
  341. {$endif}
  342. {$elseif defined(CPUSPARC64)}
  343. nfixedargs: cuint;
  344. {$elseif defined(CPUPOWERPC)}
  345. {$ifndef DARWIN}
  346. nfixedargs: cuint;
  347. {$endif}
  348. {$endif}
  349. end;
  350. pffi_raw = ^ffi_raw;
  351. ffi_raw = record
  352. case longint of
  353. 0: (sint: ffi_sarg);
  354. 1: (uint: ffi_arg);
  355. 2: (flt: cfloat);
  356. 3: (data: array[0..FFI_SIZEOF_ARG] of cchar);
  357. 4: (ptr: Pointer);
  358. end;
  359. {$if (FFI_SIZEOF_JAVA_ARG = 4) and (FFI_SIZEOF_ARG = 8)}
  360. (* This is a special case for mips64/n32 ABI (and perhaps others) where
  361. sizeof(void * ) is 4 and FFI_SIZEOF_ARG is 8. *)
  362. ffi_java_raw = record
  363. case longint of
  364. 0: (sint: ffi_sarg);
  365. 1: (uint: ffi_arg);
  366. 2: (flt: cfloat);
  367. 3: (data: array[0..FFI_SIZEOF_JAVA_ARG] of cchar);
  368. 4: (ptr: Pointer);
  369. end;
  370. {$else}
  371. ffi_java_raw = ffi_raw;
  372. {$endif}
  373. pffi_java_raw = ^ffi_java_raw;
  374. ffi_fn = procedure;
  375. procedure ffi_raw_call(cif: pffi_cif;
  376. fn: ffi_fn;
  377. rvalue: Pointer;
  378. avalue: pffi_raw); cdecl; external ffilibrary name 'ffi_raw_call';
  379. procedure ffi_ptrarray_to_raw(cif: pffi_cif; args: PPointer; raw: pffi_raw); cdecl; external ffilibrary name 'ffi_ptrarray_to_raw';
  380. procedure ffi_raw_to_ptrarray(cif: pffi_cif; raw: pffi_raw; args: PPointer); cdecl; external ffilibrary name 'ffi_raw_to_ptrarray';
  381. function ffi_raw_size(cif: pffi_cif): csize_t; cdecl; external ffilibrary name 'ffi_raw_size';
  382. (* This is analogous to the raw API, except it uses Java parameter
  383. packing, even on 64-bit machines. I.e. on 64-bit machines longs
  384. and doubles are followed by an empty 64-bit word. *)
  385. procedure ffi_java_raw_call(cif: pffi_cif;
  386. fn: ffi_fn;
  387. rvalue: Pointer;
  388. avalue: pffi_java_raw); cdecl; external ffilibrary name 'ffi_java_raw_call';
  389. procedure ffi_java_ptrarray_to_raw(cif: pffi_cif; args: PPointer; raw: pffi_java_raw); cdecl; external ffilibrary name 'ffi_java_ptrarray_to_raw';
  390. procedure ffi_java_raw_to_ptrarray(cif: pffi_cif; raw: pffi_java_raw; args: PPointer); cdecl; external ffilibrary name 'ffi_java_raw_to_ptrarray';
  391. function ffi_java_raw_size(cif: pffi_cif): csize_t; cdecl; external ffilibrary name 'ffi_java_raw_size';
  392. (* ---- Definitions for closures ----------------------------------------- *)
  393. {$if FFI_CLOSURES}
  394. type
  395. ffi_closure_fun = procedure(cif: pffi_cif; arg1: Pointer; arg2: PPointer; arg3: Pointer); cdecl;
  396. { ToDo: align 8 }
  397. ffi_closure = record
  398. {$if FFI_EXEC_TRAMPOLINE_TABLE}
  399. trampoline_table: Pointer;
  400. trampoline_table_entry: Pointer;
  401. {$else}
  402. tramp: array[0..FFI_TRAMPOLINE_SIZE] of cchar;
  403. {$endif}
  404. cif: pffi_cif;
  405. fun: ffi_closure_fun;
  406. user_data: Pointer;
  407. end;
  408. pffi_closure = ^ffi_closure;
  409. function ffi_closure_alloc(size: csize_t; code: PPointer): Pointer; cdecl; external ffilibrary name 'ffi_closure_alloc';
  410. procedure ffi_closure_free(clo: Pointer); cdecl; external ffilibrary name 'ffi_closure_free';
  411. function ffi_prep_closure(clo: pffi_closure;
  412. cif: pffi_cif;
  413. fun: ffi_closure_fun;
  414. user_data: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_closure'; deprecated 'use ffi_prep_closure_loc instead';
  415. function ffi_prep_closure_loc(clo: pffi_closure;
  416. cif: pffi_cif;
  417. fun: ffi_closure_fun;
  418. user_data: Pointer;
  419. codeloc: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_closure_loc';
  420. type
  421. ffi_raw_closure_fun = procedure(cif: pffi_cif; arg1: Pointer; arg2: pffi_raw; arg3: Pointer); cdecl;
  422. ffi_java_raw_closure_fun = procedure(cif: pffi_cif; arg1: Pointer; arg2: pffi_java_raw; arg3: Pointer); cdecl;
  423. { ToDo: pack 8 for __sgi aka MIPS? }
  424. ffi_raw_closure = record
  425. {$if FFI_EXEC_TRAMPOLINE_TABLE}
  426. trampoline_table: Pointer;
  427. trampoline_table_entry: Pointer;
  428. {$else}
  429. tramp: array[0..FFI_TRAMPOLINE_SIZE] of cchar;
  430. {$endif}
  431. cif: pffi_cif;
  432. {$if not FFI_NATIVE_RAW_API}
  433. (* If this is enabled, then a raw closure has the same layout
  434. as a regular closure. We use this to install an intermediate
  435. handler to do the transaltion, void** -> ffi_raw*. *)
  436. translate_args: ffi_closure_fun;
  437. this_closure: Pointer;
  438. {$endif}
  439. fun: ffi_raw_closure_fun;
  440. user_data: Pointer;
  441. end;
  442. pffi_raw_closure = ^ffi_raw_closure;
  443. { ToDo: pack 8 for __sgi aka MIPS? }
  444. ffi_java_raw_closure = record
  445. {$if FFI_EXEC_TRAMPOLINE_TABLE}
  446. trampoline_table: Pointer;
  447. trampoline_table_entry: Pointer;
  448. {$else}
  449. tramp: array[0..FFI_TRAMPOLINE_SIZE] of cchar;
  450. {$endif}
  451. cif: pffi_cif;
  452. {$if not FFI_NATIVE_RAW_API}
  453. (* If this is enabled, then a raw closure has the same layout
  454. as a regular closure. We use this to install an intermediate
  455. handler to do the transaltion, void** -> ffi_raw*. *)
  456. translate_args: ffi_closure_fun;
  457. this_closure: Pointer;
  458. {$endif}
  459. fun: ffi_java_raw_closure_fun;
  460. user_data: Pointer;
  461. end;
  462. pffi_java_raw_closure = ^ffi_java_raw_closure;
  463. function ffi_prep_raw_closure(clo: pffi_raw_closure;
  464. cif: pffi_cif;
  465. fun: ffi_raw_closure_fun;
  466. user_data: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_raw_closure';
  467. function ffi_prep_raw_closure_loc(clo: pffi_raw_closure;
  468. cif: pffi_cif;
  469. fun: ffi_raw_closure_fun;
  470. user_data: Pointer;
  471. codeloc: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_raw_closure_loc';
  472. function ffi_prep_java_raw_closure(clo: pffi_java_raw_closure;
  473. cif: pffi_cif;
  474. fun: ffi_java_raw_closure_fun;
  475. user_data: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_java_raw_closure';
  476. function ffi_prep_java_raw_closure_loc(clo: pffi_java_raw_closure;
  477. cif: pffi_cif;
  478. fun: ffi_java_raw_closure_fun;
  479. user_data: Pointer;
  480. codeloc: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_java_raw_closure_loc';
  481. {$endif}
  482. {$if FFI_GO_CLOSURES}
  483. type
  484. ffi_go_closure = record
  485. tramp: Pointer;
  486. cif: pffi_cif;
  487. fun: ffi_closure_fun;
  488. end;
  489. pffi_go_closure = ^ffi_go_closure;
  490. function ffi_prep_go_closure(clo: pffi_go_closure; cif: pffi_cif; fun: ffi_closure_fun): ffi_status; cdecl; external ffilibrary name 'ffi_prep_go_closure';
  491. procedure ffi_call_go(cif: pffi_cif; fn: ffi_fn; rvalue: Pointer; avalue: PPointer; closure: Pointer); cdecl; external ffilibrary name 'ffi_call_go';
  492. {$endif}
  493. (* ---- Public interface definition -------------------------------------- *)
  494. function ffi_prep_cif(cif: pffi_cif;
  495. abi: ffi_abi;
  496. nargs: cuint;
  497. rtype: pffi_type;
  498. atypes: ppffi_type): ffi_status; cdecl; external ffilibrary name 'ffi_prep_cif';
  499. function ffi_prep_cif_var(cif: pffi_cif;
  500. abi: ffi_abi;
  501. nfixedargs: cuint;
  502. ntotalargs: cuint;
  503. rtype: pffi_type;
  504. atypes: ppffi_type): ffi_status; cdecl; external ffilibrary name 'ffi_prep_cif_var';
  505. procedure ffi_call(cif: pffi_cif;
  506. fn: ffi_fn;
  507. rvalue: Pointer;
  508. avalue: PPointer); cdecl; external ffilibrary name 'ffi_call';
  509. function ffi_get_struct_offsets(abi: ffi_abi; struct_type: pffi_type;
  510. offsets: pcsize_t): ffi_status; cdecl; external ffilibrary name 'ffi_get_struct_offsets';
  511. const
  512. _FFI_TYPE_VOID = 0;
  513. _FFI_TYPE_INT = 1;
  514. _FFI_TYPE_FLOAT = 2;
  515. _FFI_TYPE_DOUBLE = 3;
  516. {$ifdef HAVE_LONG_DOUBLE}
  517. _FFI_TYPE_LONGDOUBLE = 4;
  518. {$else}
  519. _FFI_TYPE_LONGDOUBLE = _FFI_TYPE_DOUBLE;
  520. {$endif}
  521. _FFI_TYPE_UINT8 = 5;
  522. _FFI_TYPE_SINT8 = 6;
  523. _FFI_TYPE_UINT16 = 7;
  524. _FFI_TYPE_SINT16 = 8;
  525. _FFI_TYPE_UINT32 = 9;
  526. _FFI_TYPE_SINT32 = 10;
  527. _FFI_TYPE_UINT64 = 11;
  528. _FFI_TYPE_SINT64 = 12;
  529. _FFI_TYPE_STRUCT = 13;
  530. _FFI_TYPE_POINTER = 14;
  531. _FFI_TYPE_COMPLEX = 15;
  532. _FFI_TYPE_LAST = _FFI_TYPE_COMPLEX;
  533. { ToDo: can we do without the platform specific types? }
  534. implementation
  535. end.