The Julia documentation shows examples of how to call Base Julia functions from C (e.g. sqrt), which I've been successful in replicating. What I'm really interested in doing is calling locally developed Julia modules and it's not at all clear from the documentation how one would call non-Base functions. There are some discussion threads on the issue from a few years ago, but the APIs appear to have changed in the meantime. Any pointers would be appreciated.
The reason why jl_eval_string("using SomeModule") returns NULL is simply because using SomeModule returns nothing.
You can use functions from other modules by first importing the module, and then retrieving function objects from that Julia module into C. For example, let's use the package GR and its plot function. We can get the plot function with
jl_eval_string("using GR") // this returns nothing
jl_module_t* GR = (jl_module_t *)jl_eval_string("GR") // this returns the module
/* get `plot` function */
jl_function_t *plot = jl_get_function(GR, "plot");
Here we passed GR module as the first argument to jl_get_function. We can, knowing the fact that things will be loaded into the module Main and plot is exported from GR, use the following snippet instead to do the same. Note that jl_main_module holds a pointer to the module Main.
jl_eval_string("using GR")
/* get `plot` function */
jl_function_t *plot = jl_get_function(jl_main_module, "plot");
We can also use plots qualified name.
/* get `plot` function */
jl_function_t *plot = jl_get_function(jl_main_module, "GR.plot");
That said, here is the complete example plotting an array of values using GR. The example uses the first style to get the function GR.plot.
#include <julia.h>
JULIA_DEFINE_FAST_TLS() // only define this once, in an executable (not in a shared library) if you want fast code.
#include <stdio.h>
int main(int argc, char *argv[])
{
/* required: setup the Julia context */
jl_init();
/* create a 1D array of length 100 */
double length = 100;
double *existingArray = (double*)malloc(sizeof(double)*length);
/* create a *thin wrapper* around our C array */
jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, length, 0);
/* fill in values */
double *xData = (double*)jl_array_data(x);
for (int i = 0; i < length; i++)
xData[i] = i * i;
/* import `Plots` into `Main` module with `using`*/
jl_eval_string("using GR");
jl_module_t* GR = (jl_module_t *)jl_eval_string("GR");;
/* get `plot` function */
jl_function_t *plot = jl_get_function(GR, "plot");
/* create the plot */
jl_value_t* p = jl_call1(plot, (jl_value_t*)x);
/* display the plot */
jl_function_t *disp = jl_get_function(jl_base_module, "display");
jl_call1(disp, p);
getchar();
/* exit */
jl_atexit_hook(0);
return 0;
}
Including a Julia module from a local file and use it in C
I do not know what is exactly meant by a local Julia package, but, you can include your files and then import the modules in those files to do the same. Here is an example module.
# Hello.jl
module Hello
export foo!
foo!(x) = (x .*= 2) # multiply entries of x by 2 inplace
end
To include this file you need to use jl_eval_string("Base.include(Main, \"Hello.jl\")");. For some reason, embedded Julia cannot access include directly. You need to use Base.include(Main, "/path/to/file") instead.
jl_eval_string("Base.include(Main, \"Hello.jl\")");
jl_eval_string("using Main.Hello"); // or just '.Hello'
jl_module_t* Hello = (jl_module_t *)jl_eval_string("Main.Hello"); // or just .Hello
Here is the complete example in C.
#include <julia.h>
JULIA_DEFINE_FAST_TLS() // only define this once, in an executable (not in a shared library) if you want fast code.
#include <stdio.h>
int main(int argc, char *argv[])
{
/* required: setup the Julia context */
jl_init();
/* create a 1D array of length 100 */
double length = 100;
double *existingArray = (double*)malloc(sizeof(double)*length);
/* create a *thin wrapper* around our C array */
jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, length, 0);
JL_GC_PUSH1(&x);
/* fill in values */
double *xData = (double*)jl_array_data(x);
for (int i = 0; i < length; i++)
xData[i] = i * i;
/* import `Hello` module from file Hello.jl */
jl_eval_string("Base.include(Main, \"Hello.jl\")");
jl_eval_string("using Main.Hello");
jl_module_t* Hello = (jl_module_t *)jl_eval_string("Main.Hello");
/* get `foo!` function */
jl_function_t *foo = jl_get_function(Hello, "foo!");
/* call the function */
jl_call1(foo, (jl_value_t*)x);
/* print new values of x */
for (int i = 0; i < length; i++)
printf("%.1f ", xData[i]);
printf("\n");
JL_GC_POP();
getchar();
/* exit */
jl_atexit_hook(0);
return 0;
}
Related
Doing some experiments using python (means python3) for preparing data (also as sending them to wire - SPI) shows it is slow (having limited system). So I was thinking of creation of extension module written in C to defer the critical stuff to. I would like either:
the python script would have access to memory block created by the malloc() in the extension module hopefully transparently convertible to bytearray
the extension module would get the pointer to bytearray object created in python hopefully transparently convertible to void *
The goal is to have zero copy also as zero conversion memory block accessible by both python (as bytearray) and extension module (as void *).
Is there any method, how to achieve this?
OK, it seems to be simpler than expected ;-)
bytearray provides direct support for accessing underlying memory block, which is exactly what is needed
there is a format specifier for extracting bytearray object from function call argument list
C extension module [test.c]:
#include <Python.h>
#include <stdint.h>
/* Forward prototype declaration */
static PyObject *transform(PyObject *self, PyObject *args);
/* Methods exported by this extension module */
static PyMethodDef test_methods[] =
{
{"transform", transform, METH_VARARGS, "testing buffer transformation"},
{NULL, NULL, 0, NULL}
};
/* Extension module definition */
static struct PyModuleDef test_module =
{
PyModuleDef_HEAD_INIT,
"BytearrayTest",
NULL,
-1,
test_methods,
};
/*
* The test function
*/
static PyObject *transform(PyObject *self, PyObject *args)
{
PyByteArrayObject *byte_array;
uint8_t *buff;
int buff_len = 0;
int i;
/* Get the bytearray object */
if (!PyArg_ParseTuple(args, "Y", &byte_array))
return NULL;
buff = (uint8_t *)(byte_array->ob_bytes); /* data */
buff_len = byte_array->ob_alloc; /* length */
/* Perform desired transformation */
for (i = 0; i < buff_len; ++i)
buff[i] += 65;
/* Return void */
Py_INCREF(Py_None);
return Py_None;
}
/* Mandatory extension module init function */
PyMODINIT_FUNC PyInit_BytearrayTest(void)
{
return PyModule_Create(&test_module);
}
C extension module build/deployment script [setup.py]:
#!/usr/bin/python3
from distutils.core import setup, Extension
module = Extension('BytearrayTest', sources = ['test.c'])
setup (name = 'BytearrayTest',
version = '1.0',
description = 'This is a bytearray test package',
ext_modules = [module])
Build/install the extension module:
# ./setup.py build
# ./setup.py install
Test it:
>>> import BytearrayTest
>>> a = bytearray(16); a
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
>>> BytearrayTest.transform(a); a
bytearray(b'AAAAAAAAAAAAAAAA')
>>>
I call C code via .Call("foo", <args>), where foo calls other C
functions, computes the result and returns it. The result is a list
of length 3 and I would like to name this list. To this end, foo
does this:
/* Construct result list from variables containing the results */
SEXP res = PROTECT(allocVector(VECSXP, 3)); /* list of length 3 */
SET_VECTOR_ELT(res, 0, ScalarReal(a)); /* numeric(1) */
SET_VECTOR_ELT(res, 1, somenumericvector); /* numeric(<some length>) */
SET_VECTOR_ELT(res, 2, ScalarInteger(i)); /* integer(1) */
/* Name components and return */
SEXP nms = PROTECT(allocVector(STRSXP, 3)); /* names as SEXP */
char *nms_ = CHAR(STRING_ELT(nms, 0)); /* pointer to names */
char *names[3] = {"result_numeric", "result_numeric_vector", "result_integer"};
for(i = 0; i < 3; i++) nms_[i] = names[i];
setAttrib(res, R_NamesSymbol, nms);
UNPROTECT(1);
return res;
Is this a/the correct way of constructing a named list of length 3?
The C function indeed returns back to R but once I assign the output to a
variable in R, I immediately get a segmentation fault. What might be wrong? I
can put 'debug statement's' (simple printf("...\n") right before the above 'return
res;' and they are executed fine.
Is there any convenient way to debug C code called from R?
An alternative to BrodieG's answer is to use mkNamed from Rinlinedfuns.h (which contains an example of how to use mkNamed).
/* Construct named result list from variables containing the results */
const char *names[] = {"result_numeric", "result_numeric_vector",
"result_integer", ""}; /* note the null string */
SEXP res = PROTECT(mkNamed(VECSXP, names)); /* list of length 3 */
SET_VECTOR_ELT(res, 0, ScalarReal(a)); /* numeric(1) */
SET_VECTOR_ELT(res, 1, somenumericvector); /* numeric(<some length>) */
SET_VECTOR_ELT(res, 2, ScalarInteger(i)); /* integer(1) */
UNPROTECT(1);
return res;
Since you ask for the plain vanilla way, you need to create an R character vector from the C strings using mkChar and SET_STRING_ELT:
for(i = 0; i < 3; i++) SET_STRING_ELT(nms, i, mkChar(names[i]));
Right now, you are trying to use the raw C string as an R object, which won't work.
Re:debugging, you can use PrintValue in C code to print out R objects.
All this said, unless you have a very specific reason for wanting plain vanilla, you should consider Rcpp.
Per #nrussell's good advice, a solution in a single statement (broken over four lines for legibility)
R> cppFunction('List marius(double a, NumericVector b, int c) \
{ return List::create(Named("resnum")=a,\
Named("resvec")=b, \
Named("resint")=c); }')
R> marius(1.2, sqrt(3:5), 42L)
$resnum
[1] 1.2
$resvec
[1] 1.73205 2.00000 2.23607
$resint
[1] 42
R>
Instead of using the lua_CFunction signature for writing methods to be called from Lua, I'd like to use my own function signature that simplifies the export process.
void foo(call_t *call)
{
int a;
char *b;
char *c;
table_t *d;
/* reading arguments */
a = read_integer(call);
b = read_string(call);
/* do something... */
/* writing arguments */
write_string(call, c);
write_table(call, d);
}
/* export to Lua */
export("foo", foo);
So far, all I can think of doing is having a single lua_CFunction that calls the wrapper function from a table. However, I don't know how to associate a Lua function with a C function and table index so as to effectively make the Lua function a closure. Something like this:
lua_register_with_data(state, "foo", base_function, FOO_INDEX);
How can I make this happen?
I figured it out after all. I guess this proves how useful rubber duck debugging is.
I just registered the base function along with the actual function index as an upvalue.
function_t table[FUNCTION_COUNT];
/* lookup function using upvalue */
int base_function(lua_State *state)
{
int index;
call_t call;
call.state = state;
call.argument_index = 1;
call.return_count = 0;
index = lua_tointeger(state, lua_upvalueindex(1));
table[index](&call);
/* return_count is incremented by write_* functions */
return(call.return_count);
}
/* register function as closure */
table[FOO_INDEX] = foo;
lua_pushinteger(state, FOO_INDEX);
lua_pushcclosure(state, base_function, 1);
lua_setglobal(state, "foo");
I am learning gsl_rng library and found an interesting question.
I understand that the environment variables (GSL_RNG_TYPE and GSL_RNG_SEED) can be used to set library variables (gsl_rng_default and gsl_rng_default_seed) during run time (without re-compile). You just need to add gsl_rng_env_setup() and then change these two variables in terminal before do ./a.out.
However, if I specifically set the gsl_rng_default and gsl_rng_default_seed in the code (eg. use "taus" and "12"), with the same program compiled, now I cannot change the seed value at run time but can still change the generator type.
I am new to this stuff so probably I missed something. But can anyone help me understand why this happen? Why do these two variables behave differently? Is there an order or over-write problem?
Here is my code (simple practice):
#include <stdio.h>
#include <gsl/gsl_rng.h>
int main (void)
{
const gsl_rng_type * T; /*generator type*/
gsl_rng * r; /*rng instance*/
int i, n = 20;
gsl_rng_env_setup(); /*read from environment variable*/
T = gsl_rng_default; /*choose default generator type*/
gsl_rng_default = gsl_rng_mt19937;
gsl_rng_default_seed = 12;
r = gsl_rng_alloc (T); /*create an instance*/
for (i = 0; i < n; i++)
{
double u = gsl_rng_uniform (r);
printf ("%.5f\n", u);
}
gsl_rng_free (r); /*free all memory associated with r*/
return 0;
}
If we step through the code in execution order, we see what happens:
gsl_rng_env_setup(); /*read from environment variable*/
so gsl_rnd_default and gsl_rng_default_seed now contain the values from the environment, or if they weren't set, the library defaults.
T = gsl_rng_default; /*choose default generator type*/
T now contains a copy of the environment value
gsl_rng_default = gsl_rng_mt19937;
gsl_rng_default_seed = 12;
now we've overwritten both the values from earlier
r = gsl_rng_alloc (T); /*create an instance*/
At this point, since gsl_rng_alloc() uses the generator type we pass in the parameter, it doesn't matter that gsl_rng_default was overwritten because we're passing T, and that still contains its copy of the value from beforehand. However, since gsl_rng_alloc() will go ahead and use the current value of gsl_rnd_default, it gets the 12 that we put there.
If you were to assign your default values before calling gsl_rng_env_setup(), you'd overwrite the library defaults, then those values you set will be overwritten if the environment variables are set, or passed through if they aren't, which seems like the behaviour you really want.
When trying to mount a VTreeFS filesystem with a set of arguments (by using options -o when mounting) we want to let it fail cleanly if the user doesn't use the predefined arguments correctly. Currently we get this nasty error message when we do not mount the filesystem and let the main return 0. We basically want the filesystem to not be mounted if the arguments are inorrect
Current situations
mount -t filesystemtest -o testarguments none /mnt/filesystemtest
Arguments invalid
RS: service 'fs_00021' exited uring initialization
filesystemtest 109710 0xab6e 0x65f1 0x618d 0x6203 0x98ba 0x1010
Request to RS failed: unknown error (error 302)
mount: couldn't run /bin/sercie up /sbin/filesystemtest -label 'fs_00021'-args ''
mount: Can't mount none on /mnt/filesystemtest/: unknown error
Preferred situation
mount -t filesystemtest -o testarguments none /mnt/filesystemtest
Arguments invalid
Basically we wan't to know how to return a clean error message, when not calling start_vtreefs like below. The below example is not our actualy code and doesn't actually use arguments, but as an example there should be a way to have this piece of code to fail always. (sorry for that):
#include <minix/drivers.h>
#include <minix/vtreefs.h>
#include <sys/stat.h>
#include <time.h>
#include <assert.h>
static void my_init_hook(void)
{
/* This hook will be called once, after VTreeFS has initialized.
*/
struct inode_stat file_stat;
struct inode *inode;
/* We create one regular file in the root directory. The file is
* readable by everyone, and owned by root. Its size as returned by for
* example stat() will be zero, but that does not mean it is empty.
* For files with dynamically generated content, the file size is
* typically set to zero.
*/
file_stat.mode = S_IFREG | 0444;
file_stat.uid = 0;
file_stat.gid = 0;
file_stat.size = 0;
file_stat.dev = NO_DEV;
/* Now create the actual file. It is called "test" and does not have an
* index number. Its callback data value is set to 1, allowing it to be
* identified with this number later.
*/
inode = add_inode(get_root_inode(), "test", NO_INDEX, &file_stat, 0,
(cbdata_t) 1);
assert(inode != NULL);
}
static int my_read_hook(struct inode *inode, off_t offset, char **ptr,
size_t *len, cbdata_t cbdata)
{
/* This hook will be called every time a regular file is read. We use
* it to dyanmically generate the contents of our file.
*/
static char data[26];
const char *str;
time_t now;
/* We have only a single file. With more files, cbdata may help
* distinguishing between them.
*/
assert((int) cbdata == 1);
/* Generate the contents of the file into the 'data' buffer. We could
* use the return value of ctime() directly, but that would make for a
* lousy example.
*/
time(&now);
str = ctime(&now);
strcpy(data, str);
/* If the offset is beyond the end of the string, return EOF. */
if (offset > strlen(data)) {
*len = 0;
return OK;
}
/* Otherwise, return a pointer into 'data'. If necessary, bound the
* returned length to the length of the rest of the string. Note that
* 'data' has to be static, because it will be used after this function
* returns.
*/
*ptr = data + offset;
if (*len > strlen(data) - offset)
*len = strlen(data) - offset;
return OK;
}
/* The table with callback hooks. */
struct fs_hooks my_hooks = {
my_init_hook,
NULL, /* cleanup_hook */
NULL, /* lookup_hook */
NULL, /* getdents_hook */
my_read_hook,
NULL, /* rdlink_hook */
NULL /* message_hook */
};
int main(int argc, char* argv[])
{
/* The call above never returns. This just keeps the compiler happy. */
if (argc == 1) {
// We want it to fail right now!!!!
printf("Arguments invalid. (pass option with -o)");
}
else {
struct inode_stat root_stat;
/* Fill in the details to be used for the root inode. It will be a
* directory, readable and searchable by anyone, and owned by root.
*/
root_stat.mode = S_IFDIR | 0555;
root_stat.uid = 0;
root_stat.gid = 0;
root_stat.size = 0;
root_stat.dev = NO_DEV;
/* Now start VTreeFS. Preallocate 10 inodes, which is more than we'll
* need for this example. No indexed entries are used.
*/
start_vtreefs(&my_hooks, 10, &root_stat, 0);
}
return 0;
}