JL_DLLEXPORT jl_value_t *jl_backtrace_from_here(int returnsp) { jl_svec_t *tp = NULL; jl_array_t *ip = NULL; jl_array_t *sp = NULL; JL_GC_PUSH3(&tp, &ip, &sp); if (array_ptr_void_type == NULL) { tp = jl_svec2(jl_voidpointer_type, jl_box_long(1)); array_ptr_void_type = jl_apply_type((jl_value_t*)jl_array_type, tp); } ip = jl_alloc_array_1d(array_ptr_void_type, 0); sp = returnsp ? jl_alloc_array_1d(array_ptr_void_type, 0) : NULL; const size_t maxincr = 1000; bt_context_t context; bt_cursor_t cursor; memset(&context, 0, sizeof(context)); jl_unw_get(&context); if (jl_unw_init(&cursor, &context)) { size_t n = 0, offset = 0; do { jl_array_grow_end(ip, maxincr); if (returnsp) jl_array_grow_end(sp, maxincr); n = jl_unw_stepn(&cursor, (uintptr_t*)jl_array_data(ip) + offset, returnsp ? (uintptr_t*)jl_array_data(sp) + offset : NULL, maxincr); offset += maxincr; } while (n > maxincr); jl_array_del_end(ip, maxincr - n); if (returnsp) jl_array_del_end(sp, maxincr - n); } jl_value_t *bt = returnsp ? (jl_value_t*)jl_svec2(ip, sp) : (jl_value_t*)ip; JL_GC_POP(); return bt; }
jl_value_t *jl_readuntil(ios_t *s, uint8_t delim) { jl_array_t *a; // manually inlined common case char *pd = (char*)memchr(s->buf+s->bpos, delim, s->size - s->bpos); if (pd) { size_t n = pd-(s->buf+s->bpos)+1; a = jl_alloc_array_1d(jl_array_uint8_type, n); memcpy(jl_array_data(a), s->buf+s->bpos, n); s->bpos += n; } else { a = jl_alloc_array_1d(jl_array_uint8_type, 80); ios_t dest; ios_mem(&dest, 0); ios_setbuf(&dest, a->data, 80, 0); size_t n = ios_copyuntil(&dest, s, delim); if (dest.buf != a->data) { a = jl_takebuf_array(&dest); } else { #ifdef STORE_ARRAY_LEN a->length = n; #endif a->nrows = n; ((char*)a->data)[n] = '\0'; } } return (jl_value_t*)a; }
jl_value_t *jl_readuntil(ios_t *s, uint8_t delim) { jl_array_t *a; // manually inlined common case char *pd = (char*)memchr(s->buf+s->bpos, delim, s->size - s->bpos); if (pd) { size_t n = pd-(s->buf+s->bpos)+1; a = jl_alloc_array_1d(jl_array_uint8_type, n); memcpy(jl_array_data(a), s->buf+s->bpos, n); s->bpos += n; } else { a = jl_alloc_array_1d(jl_array_uint8_type, 80); ios_t dest; jl_ios_mem(&dest, 0); ios_setbuf(&dest, a->data, 80, 0); size_t n = ios_copyuntil(&dest, s, delim); if (dest.buf != a->data) { a = jl_takebuf_array(&dest); } else { a->length = n; a->nrows = n; ((char*)a->data)[n] = '\0'; } } JL_GC_PUSH(&a); jl_struct_type_t* string_type = u8_isvalid(a->data, a->length) == 1 ? // ASCII jl_ascii_string_type : jl_utf8_string_type; jl_value_t *str = alloc_2w(); str->type = (jl_type_t*)string_type; jl_fieldref(str,0) = (jl_value_t*)a; JL_GC_POP(); return str; }
JL_DLLEXPORT jl_value_t *jl_readuntil(ios_t *s, uint8_t delim, uint8_t str, uint8_t chomp) { jl_array_t *a; // manually inlined common case char *pd = (char*)memchr(s->buf + s->bpos, delim, (size_t)(s->size - s->bpos)); if (pd) { size_t n = pd - (s->buf + s->bpos) + 1; if (str) { size_t nchomp = 0; if (chomp) { nchomp = ios_nchomp(s, n); } jl_value_t *str = jl_pchar_to_string(s->buf + s->bpos, n - nchomp); s->bpos += n; return str; } a = jl_alloc_array_1d(jl_array_uint8_type, n); memcpy(jl_array_data(a), s->buf + s->bpos, n); s->bpos += n; } else { a = jl_alloc_array_1d(jl_array_uint8_type, 80); ios_t dest; ios_mem(&dest, 0); ios_setbuf(&dest, (char*)a->data, 80, 0); size_t n = ios_copyuntil(&dest, s, delim); if (chomp && n > 0 && dest.buf[n - 1] == '\n') { n--; if (n > 0 && dest.buf[n - 1] == '\r') { n--; } int truncret = ios_trunc(&dest, n); // it should always be possible to truncate dest assert(truncret == 0); (void)truncret; // ensure the variable is used to avoid warnings } if (dest.buf != a->data) { a = jl_take_buffer(&dest); } else { #ifdef STORE_ARRAY_LEN a->length = n; #endif a->nrows = n; ((char*)a->data)[n] = '\0'; } if (str) { JL_GC_PUSH1(&a); jl_value_t *st = jl_array_to_string(a); JL_GC_POP(); return st; } } return (jl_value_t*)a; }
static jl_value_t *R_Julia_MD_NA_Factor(SEXP Var, const char *VarName) { SEXP levels = getAttrib(Var, R_LevelsSymbol); if (levels == R_NilValue) return jl_nothing; //create string array for levels in julia jl_array_t *ret1 = jl_alloc_array_1d(jl_apply_array_type(jl_ascii_string_type, 1), LENGTH(levels)); jl_value_t **retData1 = jl_array_data(ret1); for (size_t i = 0; i < jl_array_len(ret1); i++) if (!IS_ASCII(Var)) retData1[i] = jl_cstr_to_string(translateChar0(STRING_ELT(levels, i))); else retData1[i] = jl_cstr_to_string(CHAR(STRING_ELT(levels, i))); if ((LENGTH(Var)) != 0) { switch (TYPEOF(Var)) { case INTSXP: { jl_array_t *ret = jl_alloc_array_1d(jl_apply_array_type(jl_uint32_type, 1), LENGTH(Var)); JL_GC_PUSH(&ret, &ret1); int *retData = (int *)jl_array_data(ret); for (size_t i = 0; i < jl_array_len(ret); i++) { if (INTEGER(Var)[i] == NA_INTEGER) { //NA in poolarray is 0 retData[i] = 0; } else { retData[i] = INTEGER(Var)[i]; } } JL_GC_POP(); return TransArrayToPoolDataArray(ret, ret1, LENGTH(Var), VarName); break; } default: return (jl_value_t *) jl_nothing; break; }//case end return (jl_value_t *) jl_nothing; }//if length !=0 return (jl_value_t *) jl_nothing; }
// hack to expose ios_stdout to julia. we could create a new iostream pointing // to stdout, but then there would be two buffers for one descriptor, and // ios_stdout is used before julia IOStream is available, creating a potential // mess. DLLEXPORT jl_value_t *jl_stdout_stream(void) { jl_array_t *a = jl_alloc_array_1d(jl_array_uint8_type, sizeof(ios_t)); a->data = (void*)ios_stdout; jl_array_data_owner(a) = (jl_value_t*)a; return (jl_value_t*)a; }
DLLEXPORT jl_value_t *jl_module_usings(jl_module_t *m) { jl_array_t *a = jl_alloc_array_1d(jl_array_any_type, 0); JL_GC_PUSH1(&a); for(int i=(int)m->usings.len-1; i >= 0; --i) { jl_array_grow_end(a, 1); jl_module_t *imp = (jl_module_t*)m->usings.items[i]; jl_cellset(a,jl_array_dim0(a)-1, (jl_value_t*)imp); } JL_GC_POP(); return (jl_value_t*)a; }
// copy a :lambda Expr into its LambdaInfo representation static void jl_lambda_info_set_ast(jl_lambda_info_t *li, jl_expr_t *ast) { assert(jl_is_expr(ast)); jl_expr_t *bodyex = (jl_expr_t*)jl_exprarg(ast, 2); assert(jl_is_expr(bodyex)); jl_array_t *body = bodyex->args; li->code = (jl_value_t*)body; jl_gc_wb(li, li->code); if (has_meta(body, pure_sym)) li->pure = 1; jl_array_t *vinfo = (jl_array_t*)jl_exprarg(ast, 1); jl_array_t *vis = (jl_array_t*)jl_array_ptr_ref(vinfo, 0); size_t nslots = jl_array_len(vis); jl_value_t *ssavalue_types = jl_array_ptr_ref(vinfo, 2); assert(jl_is_long(ssavalue_types)); size_t nssavalue = jl_unbox_long(ssavalue_types); li->slotnames = jl_alloc_vec_any(nslots); jl_gc_wb(li, li->slotnames); li->slottypes = jl_nothing; li->slotflags = jl_alloc_array_1d(jl_array_uint8_type, nslots); jl_gc_wb(li, li->slotflags); li->ssavaluetypes = jl_box_long(nssavalue); jl_gc_wb(li, li->ssavaluetypes); int i; for(i=0; i < nslots; i++) { jl_value_t *vi = jl_array_ptr_ref(vis, i); jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(vi, 0); assert(jl_is_symbol(name)); char *str = jl_symbol_name(name); if (i > 0 && name != unused_sym) { if (str[0] == '#') { // convention for renamed variables: #...#original_name char *nxt = strchr(str + 1, '#'); if (nxt) name = jl_symbol(nxt+1); else if (str[1] == 's') // compiler-generated temporaries, #sXXX name = compiler_temp_sym; } } jl_array_ptr_set(li->slotnames, i, name); jl_array_uint8_set(li->slotflags, i, jl_unbox_long(jl_array_ptr_ref(vi, 2))); } jl_array_t *sparams = (jl_array_t*)jl_array_ptr_ref(vinfo, 3); assert(jl_is_array(sparams)); li->sparam_syms = jl_alloc_svec_uninit(jl_array_len(sparams)); jl_gc_wb(li, li->sparam_syms); for(i=0; i < jl_array_len(sparams); i++) { jl_svecset(li->sparam_syms, i, jl_array_ptr_ref(sparams, i)); } jl_array_t *args = (jl_array_t*)jl_exprarg(ast, 0); size_t narg = jl_array_len(args); li->nargs = narg; li->isva = narg > 0 && jl_is_rest_arg(jl_array_ptr_ref(args, narg - 1)); }
ValueIfNotPtrArray<T> boxArray(const T* data, size_t size) { log("boxArray(const T*) - jl_alloc_array_1d and memcpy"); jl_datatype_t* dataType = TypeTraits<UnqualifiedType<T>>::dataType(); JULIACPP_ASSERT(dataType != nullptr, "Data type not supported."); jl_value_t* arrayType = jl_apply_array_type(dataType, 1); jl_array_t* array = jl_alloc_array_1d(arrayType, size); std::memcpy(jl_array_data(array), data, sizeof(T) * size); return (jl_value_t*)array; }
JL_DLLEXPORT jl_value_t *jl_get_backtrace(void) { jl_svec_t *tp = NULL; jl_array_t *bt = NULL; JL_GC_PUSH2(&tp, &bt); if (array_ptr_void_type == NULL) { tp = jl_svec2(jl_voidpointer_type, jl_box_long(1)); array_ptr_void_type = jl_apply_type((jl_value_t*)jl_array_type, tp); } bt = jl_alloc_array_1d(array_ptr_void_type, jl_bt_size); memcpy(bt->data, jl_bt_data, jl_bt_size * sizeof(void*)); JL_GC_POP(); return (jl_value_t*)bt; }
CXX_WRAP_EXPORT jl_array_t* gc_protected() { static jl_array_t* m_arr = nullptr; if (m_arr == nullptr) { #if JULIA_VERSION_MAJOR == 0 && JULIA_VERSION_MINOR > 4 jl_value_t* array_type = jl_apply_array_type(jl_any_type, 1); m_arr = jl_alloc_array_1d(array_type, 0); #else m_arr = jl_alloc_cell_1d(0); #endif jl_set_const(g_cxx_wrap_module, jl_symbol("_gc_protected"), (jl_value_t*)m_arr); } return m_arr; }
ValueIfPtrArray<T> boxArray(const T* data, size_t size) { log("boxArray(const T*) - jl_alloc_array_1d and unbox per element"); jl_datatype_t* dataType = TypeTraits<UnqualifiedType<T>>::dataType(); JULIACPP_ASSERT(dataType != nullptr, "Data type not supported."); jl_value_t* arrayType = jl_apply_array_type(dataType, 1); jl_array_t* array = jl_alloc_array_1d(arrayType, size); jl_value_t** arrayData = (jl_value_t**)jl_array_data(array); for (size_t i = 0; i < size; i++) { arrayData[i] = box(data[i]); } return (jl_value_t*)array; }
DLLEXPORT jl_value_t *jl_module_names(jl_module_t *m, int all, int imported) { jl_array_t *a = jl_alloc_array_1d(jl_array_symbol_type, 0); JL_GC_PUSH1(&a); size_t i; void **table = m->bindings.table; for(i=1; i < m->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; if (b->exportp || ((imported || b->owner == m) && (all || m == jl_main_module))) { jl_array_grow_end(a, 1); //XXX: change to jl_arrayset if array storage allocation for Array{Symbols,1} changes: jl_cellset(a, jl_array_dim0(a)-1, (jl_value_t*)b->name); } } } JL_GC_POP(); return (jl_value_t*)a; }
static jl_array_t *jl_alloc_int_1d(size_t np, size_t len) { jl_value_t *ty; if (np < 0xFF) { ty = jl_array_uint8_type; } else if (np < 0xFFFF) { static jl_value_t *int16 = NULL; if (int16 == NULL) int16 = jl_apply_array_type(jl_uint16_type, 1); ty = int16; } else { assert(np < 0x7FFFFFFF); static jl_value_t *int32 = NULL; if (int32 == NULL) int32 = jl_apply_array_type(jl_uint32_type, 1); ty = int32; } jl_array_t *a = jl_alloc_array_1d(ty, len); memset(a->data, 0, len * a->elsize); return a; }
JL_DLLEXPORT jl_array_t *jl_alloc_vec_any(size_t n) { return jl_alloc_array_1d(jl_array_any_type, n); }
JL_DLLEXPORT jl_array_t *jl_pchar_to_array(const char *str, size_t len) { jl_array_t *a = jl_alloc_array_1d(jl_array_uint8_type, len); memcpy(a->data, str, len); return a; }
jl_array_t *jl_alloc_cell_1d(size_t n) { return jl_alloc_array_1d(jl_array_any_type, n); }
// copy a :lambda Expr into its LambdaInfo representation static void jl_lambda_info_set_ast(jl_lambda_info_t *li, jl_expr_t *ast) { assert(jl_is_expr(ast)); jl_expr_t *bodyex = (jl_expr_t*)jl_exprarg(ast, 2); assert(jl_is_expr(bodyex)); jl_array_t *body = bodyex->args; li->code = (jl_value_t*)body; jl_gc_wb(li, li->code); size_t j, n = jl_array_len(body); jl_value_t **bd = (jl_value_t**)jl_array_data((jl_array_t*)li->code); for(j=0; j < n; j++) { jl_value_t *st = bd[j]; if (jl_is_expr(st) && ((jl_expr_t*)st)->head == meta_sym) { size_t k, ins = 0, na = jl_expr_nargs(st); jl_array_t *meta = ((jl_expr_t*)st)->args; for(k=0; k < na; k++) { jl_value_t *ma = jl_array_ptr_ref(meta, k); if (ma == (jl_value_t*)pure_sym) li->pure = 1; else if (ma == (jl_value_t*)inline_sym) li->inlineable = 1; else jl_array_ptr_set(meta, ins++, ma); } if (ins == 0) bd[j] = jl_nothing; else jl_array_del_end(meta, na-ins); } } jl_array_t *vinfo = (jl_array_t*)jl_exprarg(ast, 1); jl_array_t *vis = (jl_array_t*)jl_array_ptr_ref(vinfo, 0); size_t nslots = jl_array_len(vis); jl_value_t *ssavalue_types = jl_array_ptr_ref(vinfo, 2); assert(jl_is_long(ssavalue_types)); size_t nssavalue = jl_unbox_long(ssavalue_types); li->slotnames = jl_alloc_vec_any(nslots); jl_gc_wb(li, li->slotnames); li->slottypes = jl_nothing; li->slotflags = jl_alloc_array_1d(jl_array_uint8_type, nslots); jl_gc_wb(li, li->slotflags); li->ssavaluetypes = jl_box_long(nssavalue); jl_gc_wb(li, li->ssavaluetypes); int i; for(i=0; i < nslots; i++) { jl_value_t *vi = jl_array_ptr_ref(vis, i); jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(vi, 0); assert(jl_is_symbol(name)); char *str = jl_symbol_name(name); if (i > 0 && name != unused_sym) { if (str[0] == '#') { // convention for renamed variables: #...#original_name char *nxt = strchr(str + 1, '#'); if (nxt) name = jl_symbol(nxt+1); else if (str[1] == 's') // compiler-generated temporaries, #sXXX name = compiler_temp_sym; } } jl_array_ptr_set(li->slotnames, i, name); jl_array_uint8_set(li->slotflags, i, jl_unbox_long(jl_array_ptr_ref(vi, 2))); } jl_array_t *sparams = (jl_array_t*)jl_array_ptr_ref(vinfo, 3); assert(jl_is_array(sparams)); li->sparam_syms = jl_alloc_svec_uninit(jl_array_len(sparams)); jl_gc_wb(li, li->sparam_syms); for(i=0; i < jl_array_len(sparams); i++) { jl_svecset(li->sparam_syms, i, jl_array_ptr_ref(sparams, i)); } jl_array_t *args = (jl_array_t*)jl_exprarg(ast, 0); size_t narg = jl_array_len(args); li->nargs = narg; li->isva = narg > 0 && jl_is_rest_arg(jl_array_ptr_ref(args, narg - 1)); }
jl_array_t *jl_memcpy(jl_array_t *a) { jl_array_t *b = jl_alloc_array_1d(jl_array_uint8_type, a->length); memcpy(b->data, a->data, a->length); return b; }
Array(jl_datatype_t* applied_type, const size_t n = 0) { jl_value_t* array_type = jl_apply_array_type(applied_type, 1); m_array = jl_alloc_array_1d(array_type, n); }
Array(const size_t n = 0) { jl_value_t* array_type = jl_apply_array_type(static_type_mapping<ValueT>::julia_type(), 1); m_array = jl_alloc_array_1d(array_type, n); }
int main() { jl_init(NULL); { // Simple running Julia code jl_eval_string("println(sqrt(2.0))"); } { // Accessing the return value jl_value_t *ret = jl_eval_string("sqrt(2.0)"); if (jl_is_float64(ret)) { double retDouble = jl_unbox_float64(ret); printf("sqrt(2.0) in C: %e\n", retDouble); } } { // Same as above but with function handle (more flexible) jl_function_t *func = jl_get_function(jl_base_module, "sqrt"); jl_value_t* argument = jl_box_float64(2.0); jl_value_t* ret = jl_call1(func, argument); if (jl_is_float64(ret)) { double retDouble = jl_unbox_float64(ret); printf("sqrt(2.0) in C: %e\n", retDouble); } } { // 1D arrays jl_value_t* array_type = jl_apply_array_type( jl_float64_type, 1 ); jl_array_t* x = jl_alloc_array_1d(array_type , 10); JL_GC_PUSH1(&x); double* xData = jl_array_data(x); size_t i; for(i=0; i<jl_array_len(x); i++) xData[i] = i; jl_function_t *func = jl_get_function(jl_base_module, "reverse!"); jl_call1(func, (jl_value_t*) x); printf("x = ["); for(i=0; i<jl_array_len(x); i++) printf("%e ", xData[i]); printf("]\n"); JL_GC_POP(); } { // define julia function and call it jl_eval_string("my_func(x) = 2*x"); jl_function_t *func = jl_get_function(jl_current_module, "my_func"); jl_value_t* arg = jl_box_float64(5.0); double ret = jl_unbox_float64(jl_call1(func, arg)); printf("my_func(5.0) = %f\n", ret); } { // call c function jl_eval_string("println( ccall( :my_c_sqrt, Float64, (Float64,), 2.0 ) )"); } { // check for exceptions jl_eval_string("this_function_does_not_exist()"); if (jl_exception_occurred()) { jl_show(jl_stderr_obj(), jl_exception_occurred()); jl_printf(jl_stderr_stream(), "\n"); } } jl_atexit_hook(); return 0; }