Skip to content

Commit b2bb084

Browse files
committed
Start to fill out the NCI related ops. This gets us to the point where we can successfully call a function with no args and void return.
1 parent 837fa8b commit b2bb084

File tree

2 files changed

+131
-2
lines changed

2 files changed

+131
-2
lines changed

src/ops/nqp_dyncall.ops

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,140 @@
11
BEGIN_OPS_PREAMBLE
22

3-
/* Parroty includes. */
43
#include "parrot/parrot.h"
54
#include "parrot/extend.h"
65
#include "parrot/dynext.h"
76
#include "../6model/sixmodelobject.h"
7+
#include "../6model/reprs/NativeCall.h"
8+
9+
/* This library contains just three operations: one to initialize it,
10+
* one to look up a native function and build a handle to it, and
11+
* another to actually make the call.
12+
*
13+
* It uses hashes to describe arguments and return types. The following
14+
* keys are allowable.
15+
*
16+
* XXX
17+
*/
18+
19+
/* The ID of the NativeCall REPR. */
20+
static INTVAL nc_repr_id = 0;
21+
22+
/* Grabs a NativeCall body. */
23+
static NativeCallBody * get_nc_body(PARROT_INTERP, PMC *obj) {
24+
struct SixModel_REPROps *r = REPR(obj);
25+
if (r->ID == nc_repr_id)
26+
return &((NativeCallInstance *)PMC_data(obj))->body;
27+
else
28+
return (NativeCallBody *)r->get_boxed_ref(interp, STABLE(obj),
29+
OBJECT_BODY(obj), nc_repr_id);
30+
}
831

932
END_OPS_PREAMBLE
1033

11-
inline op nqp_XXX() :base_core {
34+
/* Initialize the navtie call library. */
35+
inline op nqp_native_call_setup() :base_core {
36+
/* Register the NativeCall representation. */
37+
if (!nc_repr_id)
38+
nc_repr_id = REGISTER_DYNAMIC_REPR(interp,
39+
Parrot_str_new_constant(interp, "NativeCall"),
40+
NativeCall_initialize);
41+
}
42+
43+
44+
/* Build a native call object.
45+
*
46+
* $2 is the type of object to build. It should be of a type that is
47+
* based on or boxes the NativeCall REPR.
48+
* $3 is the name of the library to load the function from.
49+
* $4 is the name of the function to load.
50+
* $5 is a string name specifying the calling convention to use.
51+
* $6 is an nqp::list(...) of nqp::hash(...), one hash per argument.
52+
The entries in the hash describe the type of argument being passed.
53+
* $7 is an nqp::hash(...) that describes the expected return type
54+
*
55+
* Provided all is well, $1 will end up containing an object of type $2
56+
* that has been initialized with all the relevant call information and
57+
* can be used with the nqp_native_call op. There's no need to manually
58+
* release the handle; when it is no longer referenced, it will be
59+
* automatically garbage collected.
60+
*/
61+
inline op nqp_native_call_build(out PMC, in PMC, in STR, in STR, in STR, in PMC, in PMC) :base_core {
62+
PMC *result_type = $2;
63+
PMC *result = REPR($2)->allocate(interp, STABLE($2));
64+
char *lib_name = Parrot_str_to_cstring(interp, $3);
65+
char *sym_name = Parrot_str_to_cstring(interp, $4);
66+
char *convention = Parrot_str_to_cstring(interp, $5);
67+
PMC *arg_info = $6;
68+
PMC *ret_info = $7;
69+
int i;
70+
71+
/* Initialize the object; grab native call part of its body. */
72+
NativeCallBody *body = get_nc_body(interp, result);
73+
REPR(result)->initialize(interp, STABLE(result), OBJECT_BODY(result));
74+
75+
/* Try to load the library. */
76+
body->lib_name = lib_name;
77+
body->lib_handle = dlLoadLibrary(lib_name);
78+
if (!body->lib_handle) {
79+
Parrot_str_free_cstring(sym_name);
80+
Parrot_str_free_cstring(convention);
81+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
82+
"Cannot locate native library '%Ss'", $3);
83+
}
84+
85+
/* Try to locate the symbol. */
86+
body->entry_point = dlFindSymbol(body->lib_handle, sym_name);
87+
Parrot_str_free_cstring(sym_name);
88+
if (!body->entry_point) {
89+
Parrot_str_free_cstring(convention);
90+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
91+
"Cannot locate symbol '%Ss' in native library '%Ss'", $4, $3);
92+
}
93+
94+
/* Set calling convention, if any. */
95+
Parrot_str_free_cstring(convention);
96+
97+
/* Transform each of the args info structures into a flag. */
98+
99+
100+
/* Transform return argument type info a flag. */
101+
102+
103+
$1 = result;
104+
}
105+
106+
/* Makes a native call.
107+
*
108+
* $2 is the type of result to build. It can be a null if the return value
109+
* is void or can simply be discarded. If the return value is a native
110+
* type, then this type should be capable of boxing it.
111+
* $3 is an object representing the call, obtained from nqp_native_call_build.
112+
* $4 is an nqp::list(...), which contains the arguments to pass; note this
113+
* means they are in boxed form
114+
*
115+
* $1 will be populated with an instance of $2 that contains the result
116+
* of the call. If $2 was null PMC, then $1 also will be. If the call
117+
* was to return a struct, array or some other pointer type and the
118+
* result comes back as NULL, then $1 will simply be $2 (which is
119+
* presumably a type object).
120+
*/
121+
inline op nqp_native_call(out PMC, in PMC, in PMC, in PMC) :base_core {
122+
PMC *result;
123+
INTVAL args, i;
124+
125+
/* Get native call body, so we can locate the call info. */
126+
NativeCallBody *body = get_nc_body(interp, $3);
127+
128+
/* Create and set up call VM. */
129+
DCCallVM *vm = dcNewCallVM(body->num_args * sizeof(void *));
130+
131+
/* Process arguments. */
132+
/* XXX */
133+
134+
/* Call and process return values. */
135+
/* XXX */
136+
dcCallVoid(vm, body->entry_point);
137+
138+
/* Finally, free call VM. */
139+
dcFree(vm);
12140
}

tools/build/Makefile.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,7 @@ $(DYNEXT_TARGET): $(DYNPMC) $(DYNOPS) $(OPS_DIR)/$(BIGINT_OPS)$(LOAD_EXT) $(OPS_
670670
$(CP) $(DYNPMC) $(DYNEXT_DIR)
671671
$(CP) $(DYNOPS) $(DYNEXT_DIR)
672672
$(CP) $(OPS_DIR)/$(BIGINT_OPS)$(LOAD_EXT) $(DYNEXT_DIR)
673+
$(CP) $(OPS_DIR)/$(DYNCALL_OPS)$(LOAD_EXT) $(DYNEXT_DIR)
673674
$(CHMOD) 755 $(DYNEXT_TARGET)
674675
$(CHMOD) 755 $(DYNEXT_DIR)/$(OPS)$(LOAD_EXT)
675676

0 commit comments

Comments
 (0)