annotate erlang/erldc/c_src/dyncallnif.c @ 42:1e3d929e43be

- godc updated to dc 1.1 and added note about missing feature
author Tassilo Philipp
date Tue, 14 Apr 2020 18:30:17 +0200
parents 8070dae59227
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
1 /*
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
2 Copyright (c) 2014 Erik Mackdanz <erikmack@gmail.com>
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
3
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
4 Permission to use, copy, modify, and distribute this software for any
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
5 purpose with or without fee is hereby granted, provided that the above
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
6 copyright notice and this permission notice appear in all copies.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
7
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
8 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
15 */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
16
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
17 #include "erl_nif.h"
11
8070dae59227 - stripped relative path from dyncall #includes
cslag
parents: 0
diff changeset
18 #include "dyncall.h"
8070dae59227 - stripped relative path from dyncall #includes
cslag
parents: 0
diff changeset
19 #include "dyncall_signature.h"
0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
20
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
21 #include <string.h>
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
22 #include <stdio.h>
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
23
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
24 /************ Begin NIF initialization *******/
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
25
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
26 #define MAX_LIBPATH_SZ 128
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
27 #define MAX_SYMBOL_NAME_SZ 32
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
28 #define MAX_FORMAT_STRING_SZ 100
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
29 #define MAX_STRING_ARG_SZ 1024
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
30
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
31 ErlNifResourceType *g_ptrrestype, *g_vmrestype;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
32
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
33 static void noop_dtor(ErlNifEnv* env, void* obj) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
34 // When erlang gc's a ptr, no-op since we can't know how to free it.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
35 // Likewise with symbols, etc.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
36 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
37 static void vm_dtor(ErlNifEnv* env, void* obj) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
38 void** ptr = (void**)obj;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
39 dcFree(*ptr);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
40 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
41
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
42 static int nifload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
43
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
44 // Allows us to have a native pointer (to vm, lib, symbol, or user-defined) and
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
45 // pass a safe opaque handle into erlang
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
46 g_ptrrestype = enif_open_resource_type(env,"dyncall","pointer",
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
47 noop_dtor,ERL_NIF_RT_CREATE,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
48 NULL);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
49
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
50 // Works like g_ptrrestype, but requires a dtor that calls dcFree
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
51 g_vmrestype = enif_open_resource_type(env,"dyncall","vmpointer",
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
52 vm_dtor,ERL_NIF_RT_CREATE,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
53 NULL);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
54
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
55 return 0;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
56 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
57
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
58 /************ End NIF initialization *******/
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
59
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
60 #define ATOM_OK "ok"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
61 #define ATOM_ERROR "error"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
62
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
63 #define ATOM_LIB_NOT_FOUND "lib_not_found"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
64 #define ATOM_SYMBOL_NOT_FOUND "symbol_not_found"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
65 #define ATOM_BADSZ "bad_vm_size"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
66 #define ATOM_INVALID_VM "invalid_vm"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
67 #define ATOM_INVALID_LIB "invalid_lib"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
68 #define ATOM_INVALID_SYMBOL "invalid_symbol"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
69 #define ATOM_INVALID_FORMAT "invalid_format"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
70 #define ATOM_INVALID_ARG "invalid_arg"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
71 #define ATOM_NOT_IMPLEMENTED "not_implemented"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
72
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
73 static ERL_NIF_TERM new_call_vm(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
74
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
75 long vmsz = 0;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
76 if(!enif_get_long(env, argv[0], &vmsz)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
77 return enif_make_tuple2(env,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
78 enif_make_atom(env,ATOM_ERROR),
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
79 enif_make_atom(env,ATOM_BADSZ)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
80 );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
81 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
82
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
83 DCCallVM* vm = dcNewCallVM( vmsz );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
84
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
85 size_t sz = sizeof(DCCallVM*);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
86 DCpointer ptr_persistent_vm = enif_alloc_resource(g_vmrestype,sz);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
87 memcpy(ptr_persistent_vm,&vm,sz);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
88 ERL_NIF_TERM retterm = enif_make_resource(env,ptr_persistent_vm);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
89 enif_release_resource(ptr_persistent_vm);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
90
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
91 return enif_make_tuple2(env,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
92 enif_make_atom(env,ATOM_OK),
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
93 retterm
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
94 );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
95 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
96
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
97 #define MAYBE_RET_BAD_STRING_ARG(indexvar,argi,limit,retatom) \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
98 char indexvar[limit]; \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
99 indexvar[limit-1] = 0; \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
100 if(enif_get_string(env, argv[argi], indexvar, limit, ERL_NIF_LATIN1) <= 0) { \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
101 return enif_make_tuple2(env, \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
102 enif_make_atom(env,ATOM_ERROR), \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
103 enif_make_atom(env,retatom) \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
104 ); \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
105 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
106
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
107 #define RETURN_ERROR(code) return enif_make_tuple2(env, \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
108 enif_make_atom(env,ATOM_ERROR), \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
109 enif_make_atom(env,code) \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
110 );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
111
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
112 static ERL_NIF_TERM load_library(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
113 MAYBE_RET_BAD_STRING_ARG(path,0,MAX_LIBPATH_SZ,ATOM_INVALID_LIB)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
114
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
115 void* libptr = enif_dlopen(path, NULL, NULL);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
116
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
117 // Error if dlLoadLibrary returned NULL
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
118 if(!libptr) RETURN_ERROR(ATOM_LIB_NOT_FOUND)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
119
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
120 size_t sz = sizeof(void*);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
121 DCpointer ptr_persistent_lib = enif_alloc_resource(g_ptrrestype,sz);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
122 memcpy(ptr_persistent_lib,&libptr,sz);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
123 ERL_NIF_TERM retterm = enif_make_resource(env,ptr_persistent_lib);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
124 enif_release_resource(ptr_persistent_lib);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
125
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
126 return enif_make_tuple2(env,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
127 enif_make_atom(env,ATOM_OK),
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
128 retterm
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
129 );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
130 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
131
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
132 static ERL_NIF_TERM find_symbol(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
133 MAYBE_RET_BAD_STRING_ARG(path,1,MAX_SYMBOL_NAME_SZ,ATOM_INVALID_SYMBOL)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
134
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
135 void** libptr;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
136 if(!enif_get_resource(env, argv[0], g_ptrrestype, (void**)&libptr)) RETURN_ERROR(ATOM_INVALID_LIB)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
137
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
138 void* symptr = enif_dlsym(*libptr,path,NULL,NULL);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
139
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
140 size_t sz = sizeof(void*);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
141 DCpointer ptr_persistent_symbol = enif_alloc_resource(g_ptrrestype,sz);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
142 memcpy(ptr_persistent_symbol,&symptr,sz);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
143 ERL_NIF_TERM retterm = enif_make_resource(env,ptr_persistent_symbol);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
144 enif_release_resource(ptr_persistent_symbol);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
145
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
146 // Error if enif_dlsym returned NULL
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
147 if(!symptr) RETURN_ERROR(ATOM_SYMBOL_NOT_FOUND)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
148
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
149 return enif_make_tuple2(env,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
150 enif_make_atom(env,ATOM_OK),
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
151 retterm
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
152 );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
153 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
154
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
155 #define BOOL_BUF_SZ 6
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
156 #define ATOM_TRUE "true"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
157 #define ATOM_FALSE "false"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
158
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
159 static void exec_call(ErlNifEnv* env, void* vm, void* sym, char rettype,ERL_NIF_TERM *retvalue, char** error_atom) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
160 if(!sym) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
161 *error_atom = ATOM_INVALID_SYMBOL;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
162 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
163 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
164
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
165 DCpointer pret;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
166 DCfloat fret;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
167 DCdouble dret;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
168 DCint iret;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
169 DCbool bret;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
170 DCshort sret;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
171 DClong lret;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
172 DClonglong llret;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
173
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
174 char* tmpstr;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
175 size_t sz;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
176 DCpointer ptr_persistent;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
177
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
178 switch(rettype) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
179 case DC_SIGCHAR_VOID:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
180 dcCallVoid(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
181 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
182 case DC_SIGCHAR_BOOL:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
183 bret = dcCallBool(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
184 tmpstr = bret ? ATOM_TRUE : ATOM_FALSE;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
185 *retvalue = enif_make_atom(env,tmpstr);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
186 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
187 case DC_SIGCHAR_CHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
188 iret = dcCallChar(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
189 *retvalue = enif_make_int(env,(char)iret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
190 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
191 case DC_SIGCHAR_UCHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
192 iret = dcCallChar(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
193 *retvalue = enif_make_int(env,(unsigned char)iret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
194 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
195 case DC_SIGCHAR_SHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
196 sret = dcCallShort(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
197 *retvalue = enif_make_int(env,sret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
198 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
199 case DC_SIGCHAR_USHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
200 sret = dcCallShort(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
201 *retvalue = enif_make_int(env,(unsigned short)sret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
202 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
203 case DC_SIGCHAR_INT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
204 iret = dcCallInt(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
205 *retvalue = enif_make_int(env,iret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
206 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
207 case DC_SIGCHAR_UINT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
208 iret = dcCallInt(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
209 *retvalue = enif_make_int(env,(unsigned int)iret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
210 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
211 case DC_SIGCHAR_LONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
212 lret = dcCallLong(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
213 *retvalue = enif_make_long(env,lret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
214 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
215 case DC_SIGCHAR_ULONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
216 lret = dcCallLong(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
217 *retvalue = enif_make_long(env,(unsigned long)lret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
218 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
219 case DC_SIGCHAR_LONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
220 llret = dcCallLongLong(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
221 *retvalue = enif_make_int64(env,llret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
222 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
223 case DC_SIGCHAR_ULONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
224 llret = dcCallLongLong(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
225 *retvalue = enif_make_int64(env,(unsigned long long)llret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
226 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
227 case DC_SIGCHAR_FLOAT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
228 fret = dcCallFloat(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
229 *retvalue = enif_make_double(env,fret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
230 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
231 case DC_SIGCHAR_DOUBLE:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
232 dret = dcCallDouble(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
233 *retvalue = enif_make_double(env,dret);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
234 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
235 case DC_SIGCHAR_POINTER:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
236 pret = dcCallPointer(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
237 sz = sizeof(DCpointer);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
238
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
239 ptr_persistent = enif_alloc_resource(g_ptrrestype,sz);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
240 memcpy(ptr_persistent,&pret,sz);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
241 *retvalue = enif_make_resource(env,ptr_persistent);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
242 enif_release_resource(ptr_persistent);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
243 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
244 case DC_SIGCHAR_STRING:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
245 pret = dcCallPointer(vm,sym);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
246 *retvalue = enif_make_string(env,pret,ERL_NIF_LATIN1);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
247 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
248 case DC_SIGCHAR_STRUCT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
249 *error_atom=ATOM_NOT_IMPLEMENTED;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
250 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
251 default:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
252 *error_atom=ATOM_INVALID_FORMAT;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
253 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
254 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
255 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
256
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
257
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
258 static void exec_arg(ErlNifEnv* env,void* vm,char argtype,ERL_NIF_TERM argterm,char** error_atom) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
259 char carg;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
260 long int larg = -1;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
261 int iarg = -1;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
262 char sarg[MAX_STRING_ARG_SZ];
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
263 double darg = -1.0;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
264 char barg[BOOL_BUF_SZ];
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
265 ErlNifSInt64 llarg = -1;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
266 void** parg;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
267
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
268 switch(argtype) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
269 case DC_SIGCHAR_BOOL:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
270 if(!enif_get_atom(env, argterm, barg, BOOL_BUF_SZ, ERL_NIF_LATIN1)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
271 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
272 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
273 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
274 dcArgBool(vm,!strcmp(barg,ATOM_TRUE));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
275 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
276 case DC_SIGCHAR_CHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
277 if(!enif_get_int(env, argterm, &iarg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
278 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
279 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
280 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
281 dcArgChar(vm,(char)iarg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
282 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
283 case DC_SIGCHAR_UCHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
284 if(!enif_get_int(env, argterm, &iarg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
285 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
286 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
287 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
288 dcArgInt(vm,(unsigned char)iarg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
289 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
290 case DC_SIGCHAR_SHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
291 if(!enif_get_int(env, argterm, &iarg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
292 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
293 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
294 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
295 dcArgShort(vm,(short)iarg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
296 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
297 case DC_SIGCHAR_USHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
298 if(!enif_get_int(env, argterm, &iarg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
299 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
300 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
301 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
302 dcArgShort(vm,(unsigned short)iarg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
303 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
304 case DC_SIGCHAR_INT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
305 if(!enif_get_int(env, argterm, &iarg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
306 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
307 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
308 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
309 dcArgInt(vm,iarg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
310 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
311 case DC_SIGCHAR_UINT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
312 if(!enif_get_int(env, argterm, &iarg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
313 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
314 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
315 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
316 dcArgInt(vm,(unsigned int)iarg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
317 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
318 case DC_SIGCHAR_LONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
319 if(!enif_get_long(env, argterm, &larg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
320 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
321 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
322 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
323 dcArgLong(vm,larg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
324 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
325 case DC_SIGCHAR_ULONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
326 if(!enif_get_long(env, argterm, &larg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
327 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
328 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
329 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
330 dcArgLong(vm,(unsigned long)larg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
331 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
332 case DC_SIGCHAR_LONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
333 if(!enif_get_int64(env, argterm, &llarg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
334 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
335 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
336 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
337 dcArgLongLong(vm,llarg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
338 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
339 case DC_SIGCHAR_ULONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
340 if(!enif_get_int64(env, argterm, &llarg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
341 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
342 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
343 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
344 dcArgLongLong(vm,(unsigned long long)llarg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
345 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
346 case DC_SIGCHAR_FLOAT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
347 if(!enif_get_double(env, argterm, &darg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
348 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
349 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
350 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
351 dcArgFloat(vm,(float)darg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
352 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
353 case DC_SIGCHAR_DOUBLE:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
354 if(!enif_get_double(env, argterm, &darg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
355 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
356 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
357 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
358 dcArgDouble(vm,darg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
359 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
360 case DC_SIGCHAR_POINTER:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
361 if(!enif_get_resource(env, argterm, g_ptrrestype, (void**)&parg)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
362 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
363 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
364 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
365 dcArgPointer(vm,*parg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
366 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
367 case DC_SIGCHAR_STRING:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
368 if(!enif_get_string(env, argterm, sarg, MAX_STRING_ARG_SZ, ERL_NIF_LATIN1)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
369 *error_atom = ATOM_INVALID_ARG;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
370 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
371 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
372 dcArgPointer(vm,sarg);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
373 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
374 case DC_SIGCHAR_STRUCT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
375 *error_atom = ATOM_NOT_IMPLEMENTED;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
376 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
377 default:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
378 *error_atom = ATOM_INVALID_FORMAT;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
379 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
380 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
381 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
382
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
383 #define GET_VM void** vmptr; \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
384 if(!enif_get_resource(env, argv[0], g_vmrestype, (void**)&vmptr)) RETURN_ERROR(ATOM_INVALID_VM); \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
385 if(!*vmptr) RETURN_ERROR(ATOM_INVALID_VM);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
386
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
387 #define GET_SYM void** symptr; \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
388 if(!enif_get_resource(env, argv[1], g_ptrrestype, (void**)&symptr)) RETURN_ERROR(ATOM_INVALID_ARG);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
389
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
390 #define EXEC_CALL(typechar) ERL_NIF_TERM retvalue; \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
391 char* error_atom = NULL; \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
392 exec_call(env,*vmptr,*symptr,typechar,&retvalue,&error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
393
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
394 #define MAKE_CALL_RETURN if(error_atom) RETURN_ERROR(error_atom); \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
395 return enif_make_tuple2(env, \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
396 enif_make_atom(env,ATOM_OK), \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
397 retvalue \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
398 );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
399
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
400 #define EXEC_ARG(typechar) char* error_atom = NULL; \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
401 exec_arg(env,*vmptr,typechar,argv[1],&error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
402
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
403 #define MAKE_ARG_RETURN if(error_atom) RETURN_ERROR(error_atom); \
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
404 return enif_make_atom(env,ATOM_OK);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
405
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
406
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
407 static ERL_NIF_TERM arg_double(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
408 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
409 EXEC_ARG(DC_SIGCHAR_DOUBLE);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
410 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
411 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
412
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
413 static ERL_NIF_TERM call_double(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
414 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
415 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
416 EXEC_CALL(DC_SIGCHAR_DOUBLE);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
417 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
418 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
419
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
420 static ERL_NIF_TERM arg_float(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
421 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
422 EXEC_ARG(DC_SIGCHAR_FLOAT);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
423 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
424 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
425
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
426 static ERL_NIF_TERM call_float(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
427 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
428 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
429 EXEC_CALL(DC_SIGCHAR_FLOAT);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
430 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
431 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
432
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
433 static ERL_NIF_TERM arg_int(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
434 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
435 EXEC_ARG(DC_SIGCHAR_INT);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
436 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
437 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
438
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
439 static ERL_NIF_TERM call_int(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
440 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
441 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
442 EXEC_CALL(DC_SIGCHAR_INT);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
443 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
444 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
445
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
446 static ERL_NIF_TERM arg_char(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
447 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
448 EXEC_ARG(DC_SIGCHAR_CHAR);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
449 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
450 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
451
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
452 static ERL_NIF_TERM call_char(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
453 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
454 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
455 EXEC_CALL(DC_SIGCHAR_CHAR);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
456 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
457 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
458
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
459 static ERL_NIF_TERM arg_bool(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
460 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
461 EXEC_ARG(DC_SIGCHAR_BOOL);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
462 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
463 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
464
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
465 static ERL_NIF_TERM call_bool(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
466 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
467 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
468 EXEC_CALL(DC_SIGCHAR_BOOL);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
469 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
470 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
471
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
472 static ERL_NIF_TERM arg_short(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
473 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
474 EXEC_ARG(DC_SIGCHAR_SHORT);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
475 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
476 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
477
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
478 static ERL_NIF_TERM call_short(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
479 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
480 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
481 EXEC_CALL(DC_SIGCHAR_SHORT);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
482 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
483 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
484
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
485 static ERL_NIF_TERM arg_long(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
486 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
487 EXEC_ARG(DC_SIGCHAR_LONG);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
488 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
489 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
490
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
491 static ERL_NIF_TERM call_long(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
492 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
493 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
494 EXEC_CALL(DC_SIGCHAR_LONG);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
495 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
496 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
497
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
498 static ERL_NIF_TERM arg_longlong(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
499 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
500 EXEC_ARG(DC_SIGCHAR_LONGLONG);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
501 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
502 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
503
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
504 static ERL_NIF_TERM call_longlong(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
505 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
506 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
507 EXEC_CALL(DC_SIGCHAR_LONGLONG);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
508 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
509 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
510
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
511 static ERL_NIF_TERM arg_ptr(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
512 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
513 EXEC_ARG(DC_SIGCHAR_POINTER);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
514 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
515 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
516
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
517 static ERL_NIF_TERM call_ptr(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
518 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
519 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
520 EXEC_CALL(DC_SIGCHAR_POINTER);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
521 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
522 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
523
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
524 static ERL_NIF_TERM call_void(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
525 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
526 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
527 EXEC_CALL(DC_SIGCHAR_VOID);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
528
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
529 if(error_atom) RETURN_ERROR(error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
530 return enif_make_atom(env,ATOM_OK);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
531 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
532
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
533 static ERL_NIF_TERM arg_string(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
534 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
535 EXEC_ARG(DC_SIGCHAR_STRING);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
536 MAKE_ARG_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
537 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
538
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
539 static ERL_NIF_TERM call_string(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
540 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
541 GET_SYM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
542 EXEC_CALL(DC_SIGCHAR_STRING);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
543 MAKE_CALL_RETURN;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
544 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
545
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
546 static ERL_NIF_TERM mode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
547 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
548
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
549 int mode = -1;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
550 if(!enif_get_int(env, argv[1], &mode)) RETURN_ERROR(ATOM_INVALID_ARG)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
551
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
552 dcMode(*vmptr,mode);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
553 return enif_make_atom(env,ATOM_OK);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
554 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
555
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
556 static ERL_NIF_TERM get_error(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
557 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
558
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
559 DCint ret = dcGetError(*vmptr);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
560
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
561 return enif_make_tuple2(env,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
562 enif_make_atom(env,ATOM_OK),
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
563 enif_make_int(env,ret)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
564 );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
565 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
566
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
567 static ERL_NIF_TERM reset(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
568 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
569
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
570 dcReset(*vmptr);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
571 return enif_make_atom(env,ATOM_OK);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
572 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
573
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
574 static void process_formatted_args(ErlNifEnv* env,void* vm,char** format,ERL_NIF_TERM arglist,char** error_atom) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
575
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
576 ERL_NIF_TERM remaining = arglist;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
577
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
578 char sigchar;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
579 char* onechar = *format;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
580 while((sigchar=*onechar)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
581 if(sigchar==DC_SIGCHAR_ENDARG) break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
582
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
583 // If the format has more items than the arg list,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
584 // fail and call it a bad format.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
585 ERL_NIF_TERM first, rest;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
586 if(!enif_get_list_cell(env, remaining, &first, &rest)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
587 *error_atom = ATOM_INVALID_FORMAT;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
588 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
589 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
590
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
591 exec_arg(env,vm,sigchar,first,error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
592
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
593 remaining = rest;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
594 onechar++;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
595 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
596
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
597 // There are more args, but the format was exhausted
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
598 if(!enif_is_empty_list(env,remaining)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
599 *error_atom = ATOM_INVALID_FORMAT;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
600 return;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
601 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
602
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
603 *format = onechar;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
604 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
605
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
606 static ERL_NIF_TERM argf(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
607 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
608 MAYBE_RET_BAD_STRING_ARG(format,1,MAX_FORMAT_STRING_SZ,ATOM_INVALID_FORMAT);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
609
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
610 char* formatretyped = format;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
611 char* error_atom = NULL;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
612 process_formatted_args(env,*vmptr,&formatretyped, argv[2], &error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
613
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
614 if(error_atom) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
615 RETURN_ERROR(error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
616 } else return enif_make_atom(env,ATOM_OK);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
617 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
618
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
619 static ERL_NIF_TERM callf(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
620 GET_VM;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
621
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
622 void** symptr;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
623 if(!enif_get_resource(env, argv[1], g_ptrrestype, (void**)&symptr)) RETURN_ERROR(ATOM_INVALID_ARG)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
624 if(!*symptr) RETURN_ERROR(ATOM_INVALID_SYMBOL)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
625
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
626 MAYBE_RET_BAD_STRING_ARG(format,2,MAX_FORMAT_STRING_SZ,ATOM_INVALID_FORMAT);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
627
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
628 char* formatretyped = format;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
629 char* error_atom = NULL;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
630 process_formatted_args(env,*vmptr,&formatretyped, argv[3], &error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
631
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
632 if(error_atom) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
633 RETURN_ERROR(error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
634 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
635
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
636 // Get return type char, skip )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
637 char rettypechar = *(formatretyped+1);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
638
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
639 ERL_NIF_TERM retval;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
640
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
641 exec_call(env,*vmptr,*symptr,rettypechar,&retval,&error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
642
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
643 if(error_atom) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
644 RETURN_ERROR(error_atom);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
645 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
646
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
647 if(rettypechar == DC_SIGCHAR_VOID) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
648 return enif_make_atom(env,ATOM_OK);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
649 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
650
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
651 return enif_make_tuple2(env,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
652 enif_make_atom(env,ATOM_OK),
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
653 retval
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
654 );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
655 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
656
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
657 static ErlNifFunc nif_funcs[] = {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
658 {"new_call_vm", 1, new_call_vm},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
659 {"mode", 2, mode},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
660 {"get_error", 1, get_error},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
661 {"reset", 1, reset},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
662 {"load_library", 1, load_library},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
663 {"find_symbol", 2, find_symbol},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
664 {"arg_double", 2, arg_double},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
665 {"call_double", 2, call_double},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
666 {"arg_float", 2, arg_float},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
667 {"call_float", 2, call_float},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
668 {"arg_int", 2, arg_int},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
669 {"call_int", 2, call_int},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
670 {"arg_char", 2, arg_char},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
671 {"call_char", 2, call_char},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
672 {"arg_bool", 2, arg_bool},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
673 {"call_bool", 2, call_bool},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
674 {"arg_short", 2, arg_short},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
675 {"call_short", 2, call_short},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
676 {"arg_long", 2, arg_long},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
677 {"call_long", 2, call_long},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
678 {"arg_longlong", 2, arg_longlong},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
679 {"call_longlong", 2, call_longlong},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
680 {"arg_ptr", 2, arg_ptr},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
681 {"call_ptr", 2, call_ptr},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
682 {"call_void", 2, call_void},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
683 {"arg_string", 2, arg_string},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
684 {"call_string", 2, call_string},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
685
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
686 {"argf", 3, argf},
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
687 {"callf", 4, callf}
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
688 };
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
689
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
690 ERL_NIF_INIT(dyncall,nif_funcs,&nifload,NULL,NULL,NULL)