1#ifndef RUBY_DL_H
2#define RUBY_DL_H
3
4#include <ruby.h>
5
6#if !defined(FUNC_CDECL)
7#  define FUNC_CDECL(x) x
8#endif
9
10#if defined(HAVE_DLFCN_H)
11# include <dlfcn.h>
12# /* some stranger systems may not define all of these */
13#ifndef RTLD_LAZY
14#define RTLD_LAZY 0
15#endif
16#ifndef RTLD_GLOBAL
17#define RTLD_GLOBAL 0
18#endif
19#ifndef RTLD_NOW
20#define RTLD_NOW 0
21#endif
22#else
23# if defined(_WIN32)
24#   include <windows.h>
25#   define dlopen(name,flag) ((void*)LoadLibrary(name))
26#   define dlerror() strerror(rb_w32_map_errno(GetLastError()))
27#   define dlsym(handle,name) ((void*)GetProcAddress((handle),(name)))
28#   define RTLD_LAZY -1
29#   define RTLD_NOW  -1
30#   define RTLD_GLOBAL -1
31# endif
32#endif
33
34#define MAX_CALLBACK 5
35#define DLSTACK_TYPE SIGNED_VALUE
36#define DLSTACK_SIZE (20)
37#define DLSTACK_PROTO \
38    DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,\
39    DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,\
40    DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,\
41    DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE,DLSTACK_TYPE
42#define DLSTACK_ARGS(stack) \
43    (stack)[0],(stack)[1],(stack)[2],(stack)[3],(stack)[4],\
44    (stack)[5],(stack)[6],(stack)[7],(stack)[8],(stack)[9],\
45    (stack)[10],(stack)[11],(stack)[12],(stack)[13],(stack)[14],\
46    (stack)[15],(stack)[16],(stack)[17],(stack)[18],(stack)[19]
47
48#define DLSTACK_PROTO0_ void
49#define DLSTACK_PROTO1_ DLSTACK_TYPE
50#define DLSTACK_PROTO2_ DLSTACK_PROTO1_, DLSTACK_TYPE
51#define DLSTACK_PROTO3_ DLSTACK_PROTO2_, DLSTACK_TYPE
52#define DLSTACK_PROTO4_ DLSTACK_PROTO3_, DLSTACK_TYPE
53#define DLSTACK_PROTO4_ DLSTACK_PROTO3_, DLSTACK_TYPE
54#define DLSTACK_PROTO5_ DLSTACK_PROTO4_, DLSTACK_TYPE
55#define DLSTACK_PROTO6_ DLSTACK_PROTO5_, DLSTACK_TYPE
56#define DLSTACK_PROTO7_ DLSTACK_PROTO6_, DLSTACK_TYPE
57#define DLSTACK_PROTO8_ DLSTACK_PROTO7_, DLSTACK_TYPE
58#define DLSTACK_PROTO9_ DLSTACK_PROTO8_, DLSTACK_TYPE
59#define DLSTACK_PROTO10_ DLSTACK_PROTO9_, DLSTACK_TYPE
60#define DLSTACK_PROTO11_ DLSTACK_PROTO10_, DLSTACK_TYPE
61#define DLSTACK_PROTO12_ DLSTACK_PROTO11_, DLSTACK_TYPE
62#define DLSTACK_PROTO13_ DLSTACK_PROTO12_, DLSTACK_TYPE
63#define DLSTACK_PROTO14_ DLSTACK_PROTO13_, DLSTACK_TYPE
64#define DLSTACK_PROTO14_ DLSTACK_PROTO13_, DLSTACK_TYPE
65#define DLSTACK_PROTO15_ DLSTACK_PROTO14_, DLSTACK_TYPE
66#define DLSTACK_PROTO16_ DLSTACK_PROTO15_, DLSTACK_TYPE
67#define DLSTACK_PROTO17_ DLSTACK_PROTO16_, DLSTACK_TYPE
68#define DLSTACK_PROTO18_ DLSTACK_PROTO17_, DLSTACK_TYPE
69#define DLSTACK_PROTO19_ DLSTACK_PROTO18_, DLSTACK_TYPE
70#define DLSTACK_PROTO20_ DLSTACK_PROTO19_, DLSTACK_TYPE
71
72/*
73 * Add ",..." as the last argument.
74 * This is required for variable argument functions such
75 * as fprintf() on x86_64-linux.
76 *
77 * http://refspecs.linuxfoundation.org/elf/x86_64-abi-0.95.pdf
78 * page 19:
79 *
80 *   For calls that may call functions that use varargs or stdargs
81 *   (prototype-less calls or calls to functions containing ellipsis
82 *   (...) in the declaration) %al is used as hidden argument to
83 *   specify the number of SSE registers used.
84 */
85#define DLSTACK_PROTO0 void
86#define DLSTACK_PROTO1 DLSTACK_PROTO1_, ...
87#define DLSTACK_PROTO2 DLSTACK_PROTO2_, ...
88#define DLSTACK_PROTO3 DLSTACK_PROTO3_, ...
89#define DLSTACK_PROTO4 DLSTACK_PROTO4_, ...
90#define DLSTACK_PROTO4 DLSTACK_PROTO4_, ...
91#define DLSTACK_PROTO5 DLSTACK_PROTO5_, ...
92#define DLSTACK_PROTO6 DLSTACK_PROTO6_, ...
93#define DLSTACK_PROTO7 DLSTACK_PROTO7_, ...
94#define DLSTACK_PROTO8 DLSTACK_PROTO8_, ...
95#define DLSTACK_PROTO9 DLSTACK_PROTO9_, ...
96#define DLSTACK_PROTO10 DLSTACK_PROTO10_, ...
97#define DLSTACK_PROTO11 DLSTACK_PROTO11_, ...
98#define DLSTACK_PROTO12 DLSTACK_PROTO12_, ...
99#define DLSTACK_PROTO13 DLSTACK_PROTO13_, ...
100#define DLSTACK_PROTO14 DLSTACK_PROTO14_, ...
101#define DLSTACK_PROTO14 DLSTACK_PROTO14_, ...
102#define DLSTACK_PROTO15 DLSTACK_PROTO15_, ...
103#define DLSTACK_PROTO16 DLSTACK_PROTO16_, ...
104#define DLSTACK_PROTO17 DLSTACK_PROTO17_, ...
105#define DLSTACK_PROTO18 DLSTACK_PROTO18_, ...
106#define DLSTACK_PROTO19 DLSTACK_PROTO19_, ...
107#define DLSTACK_PROTO20 DLSTACK_PROTO20_, ...
108
109#define DLSTACK_ARGS0(stack)
110#define DLSTACK_ARGS1(stack) (stack)[0]
111#define DLSTACK_ARGS2(stack) DLSTACK_ARGS1(stack), (stack)[1]
112#define DLSTACK_ARGS3(stack) DLSTACK_ARGS2(stack), (stack)[2]
113#define DLSTACK_ARGS4(stack) DLSTACK_ARGS3(stack), (stack)[3]
114#define DLSTACK_ARGS5(stack) DLSTACK_ARGS4(stack), (stack)[4]
115#define DLSTACK_ARGS6(stack) DLSTACK_ARGS5(stack), (stack)[5]
116#define DLSTACK_ARGS7(stack) DLSTACK_ARGS6(stack), (stack)[6]
117#define DLSTACK_ARGS8(stack) DLSTACK_ARGS7(stack), (stack)[7]
118#define DLSTACK_ARGS9(stack) DLSTACK_ARGS8(stack), (stack)[8]
119#define DLSTACK_ARGS10(stack) DLSTACK_ARGS9(stack), (stack)[9]
120#define DLSTACK_ARGS11(stack) DLSTACK_ARGS10(stack), (stack)[10]
121#define DLSTACK_ARGS12(stack) DLSTACK_ARGS11(stack), (stack)[11]
122#define DLSTACK_ARGS13(stack) DLSTACK_ARGS12(stack), (stack)[12]
123#define DLSTACK_ARGS14(stack) DLSTACK_ARGS13(stack), (stack)[13]
124#define DLSTACK_ARGS15(stack) DLSTACK_ARGS14(stack), (stack)[14]
125#define DLSTACK_ARGS16(stack) DLSTACK_ARGS15(stack), (stack)[15]
126#define DLSTACK_ARGS17(stack) DLSTACK_ARGS16(stack), (stack)[16]
127#define DLSTACK_ARGS18(stack) DLSTACK_ARGS17(stack), (stack)[17]
128#define DLSTACK_ARGS19(stack) DLSTACK_ARGS18(stack), (stack)[18]
129#define DLSTACK_ARGS20(stack) DLSTACK_ARGS19(stack), (stack)[19]
130
131extern VALUE rb_mDL;
132extern VALUE rb_cDLHandle;
133extern VALUE rb_cDLSymbol;
134extern VALUE rb_eDLError;
135extern VALUE rb_eDLTypeError;
136
137#define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x)
138
139#define ALIGN_VOIDP  ALIGN_OF(void*)
140#define ALIGN_SHORT  ALIGN_OF(short)
141#define ALIGN_CHAR   ALIGN_OF(char)
142#define ALIGN_INT    ALIGN_OF(int)
143#define ALIGN_LONG   ALIGN_OF(long)
144#if HAVE_LONG_LONG
145#define ALIGN_LONG_LONG ALIGN_OF(LONG_LONG)
146#endif
147#define ALIGN_FLOAT  ALIGN_OF(float)
148#define ALIGN_DOUBLE ALIGN_OF(double)
149
150#define DLALIGN(ptr,offset,align) \
151    ((offset) += ((align) - ((uintptr_t)((char *)(ptr) + (offset))) % (align)) % (align))
152
153
154#define DLTYPE_VOID  0
155#define DLTYPE_VOIDP 1
156#define DLTYPE_CHAR  2
157#define DLTYPE_SHORT 3
158#define DLTYPE_INT   4
159#define DLTYPE_LONG  5
160#if HAVE_LONG_LONG
161#define DLTYPE_LONG_LONG 6
162#endif
163#define DLTYPE_FLOAT 7
164#define DLTYPE_DOUBLE 8
165#define MAX_DLTYPE 9
166
167#if SIZEOF_VOIDP == SIZEOF_LONG
168# define PTR2NUM(x)   (ULONG2NUM((unsigned long)(x)))
169# define NUM2PTR(x)   ((void*)(NUM2ULONG(x)))
170#else
171/* # error --->> Ruby/DL2 requires sizeof(void*) == sizeof(long) to be compiled. <<--- */
172# define PTR2NUM(x)   (ULL2NUM((unsigned long long)(x)))
173# define NUM2PTR(x)   ((void*)(NUM2ULL(x)))
174#endif
175
176#define BOOL2INT(x)  (((x) == Qtrue)?1:0)
177#define INT2BOOL(x)  ((x)?Qtrue:Qfalse)
178
179typedef void (*freefunc_t)(void*);
180
181struct dl_handle {
182    void *ptr;
183    int  open;
184    int  enable_close;
185};
186
187
188struct cfunc_data {
189    void *ptr;
190    char *name;
191    int  type;
192    ID   calltype;
193    VALUE wrap;
194};
195extern ID rbdl_id_cdecl;
196extern ID rbdl_id_stdcall;
197#define CFUNC_CDECL   (rbdl_id_cdecl)
198#define CFUNC_STDCALL (rbdl_id_stdcall)
199
200struct ptr_data {
201    void *ptr;
202    long size;
203    freefunc_t free;
204    VALUE wrap[2];
205};
206
207#define RDL_HANDLE(obj) ((struct dl_handle *)(DATA_PTR(obj)))
208#define RCFUNC_DATA(obj) ((struct cfunc_data *)(DATA_PTR(obj)))
209#define RPTR_DATA(obj) ((struct ptr_data *)(DATA_PTR(obj)))
210
211VALUE rb_dlcfunc_new(void (*func)(), int dltype, const char * name, ID calltype);
212int rb_dlcfunc_kind_p(VALUE func);
213VALUE rb_dlptr_new(void *ptr, long size, freefunc_t func);
214VALUE rb_dlptr_new2(VALUE klass, void *ptr, long size, freefunc_t func);
215VALUE rb_dlptr_malloc(long size, freefunc_t func);
216
217#endif
218