@@ -14,22 +14,39 @@ double my_c_sqrt(double x)
1414 return sqrt (x );
1515}
1616
17+ jl_value_t * checked_eval_string (const char * code )
18+ {
19+ jl_value_t * result = jl_eval_string (code );
20+ if (jl_exception_occurred ()) {
21+ // none of these allocate, so a gc-root (JL_GC_PUSH) is not necessary
22+ jl_call2 (jl_get_function (jl_base_module , "showerror" ),
23+ jl_stderr_obj (),
24+ jl_exception_occurred ());
25+ jl_printf (jl_stderr_stream (), "\n" );
26+ jl_atexit_hook (1 );
27+ exit (1 );
28+ }
29+ assert (result && "Missing return value but no exception occurred!" );
30+ return result ;
31+ }
32+
1733int main ()
1834{
1935 jl_init ();
2036
2137 {
22- // Simple running Julia code
38+ // Simple running of Julia code
2339
24- jl_eval_string ("println(sqrt(2.0))" );
40+ checked_eval_string ("println(sqrt(2.0))" );
2541 }
2642
2743 {
2844 // Accessing the return value
2945
30- jl_value_t * ret = jl_eval_string ("sqrt(2.0)" );
46+ jl_value_t * ret = checked_eval_string ("sqrt(2.0)" );
3147 double retDouble = jl_unbox_float64 (ret );
3248 printf ("sqrt(2.0) in C: %e\n" , retDouble );
49+ fflush (stdout );
3350 }
3451
3552 {
@@ -40,62 +57,98 @@ int main()
4057 jl_value_t * ret = jl_call1 (func , argument );
4158 double retDouble = jl_unbox_float64 (ret );
4259 printf ("sqrt(2.0) in C: %e\n" , retDouble );
60+ fflush (stdout );
4361 }
4462
4563 {
4664 // 1D arrays
4765
48- jl_value_t * array_type = jl_apply_array_type ( (jl_value_t * )jl_float64_type , 1 );
49- jl_array_t * x = jl_alloc_array_1d (array_type , 10 );
66+ jl_value_t * array_type = jl_apply_array_type ((jl_value_t * )jl_float64_type , 1 );
67+ jl_array_t * x = jl_alloc_array_1d (array_type , 10 );
68+ // JL_GC_PUSH* is required here to ensure that `x` is not deleted before
69+ // (aka, is gc-rooted until) the program reaches the corresponding JL_GC_POP()
5070 JL_GC_PUSH1 (& x );
5171
5272 double * xData = jl_array_data (x );
5373
5474 size_t i ;
55- for ( i = 0 ; i < jl_array_len (x ); i ++ )
75+ for ( i = 0 ; i < jl_array_len (x ); i ++ )
5676 xData [i ] = i ;
5777
5878 jl_function_t * func = jl_get_function (jl_base_module , "reverse!" );
5979 jl_call1 (func , (jl_value_t * ) x );
6080
6181 printf ("x = [" );
62- for ( i = 0 ; i < jl_array_len (x ); i ++ )
82+ for ( i = 0 ; i < jl_array_len (x ); i ++ )
6383 printf ("%e " , xData [i ]);
6484 printf ("]\n" );
85+ fflush (stdout );
6586
6687 JL_GC_POP ();
6788 }
6889
6990 {
70- // define julia function and call it
91+ // Defining a Julia function and calling it
7192
72- jl_eval_string ("my_func(x) = 2* x" );
93+ checked_eval_string ("my_func(x) = 2 * x" );
7394
7495 jl_function_t * func = jl_get_function (jl_current_module , "my_func" );
7596 jl_value_t * arg = jl_box_float64 (5.0 );
7697 double ret = jl_unbox_float64 (jl_call1 (func , arg ));
7798
7899 printf ("my_func(5.0) = %f\n" , ret );
100+ fflush (stdout );
79101 }
80102
81103 {
82- // call c function
104+ // Calling a C function from Julia (from C)
83105
84- jl_eval_string ("println( ccall( :my_c_sqrt, Float64, (Float64,), 2.0 ) )" );
106+ // in a shared library (exported, by name)
107+ checked_eval_string ("println( ccall(:my_c_sqrt, Float64, (Float64,), 2.0) )" );
108+
109+ // or via a pointer
110+ jl_value_t * call_by_ptr = checked_eval_string (
111+ "my_c_sqrt -> println( ccall(my_c_sqrt, Float64, (Float64,), 2.0) )" );
112+ jl_call1 (call_by_ptr , jl_box_voidpointer (my_c_sqrt ));
85113 }
86114
87115 {
88- // check for exceptions
116+ // Handling exceptions gracefully
89117
90- jl_eval_string ("this_function_does_not_exist()" );
118+ jl_value_t * f = checked_eval_string ("function this_function_has_no_methods end" );
119+ jl_call0 (f );
91120
92121 if (jl_exception_occurred ()) {
93- jl_call2 (jl_get_function (jl_base_module , "show" ), jl_stderr_obj (), jl_exception_occurred ());
122+ jl_call2 (jl_get_function (jl_base_module , "showerror" ),
123+ jl_stderr_obj (),
124+ jl_exception_occurred ());
94125 jl_printf (jl_stderr_stream (), "\n" );
95126 }
96127
97128 }
98129
130+ {
131+ // Creating and using a native C function handle
132+ // to a Julia function signature
133+
134+ checked_eval_string (
135+ "function bar()\n"
136+ " println(\"called bar\")\n"
137+ " random_return_value = 42\n"
138+ "end" );
139+ checked_eval_string (
140+ "function bar_from_c()\n"
141+ " bar()\n"
142+ " nothing\n"
143+ "end" );
144+ typedef void (* Func_VOID__VOID )(void );
145+ jl_value_t * pbar = jl_eval_string ("cfunction(bar_from_c, Void, ())" );
146+ Func_VOID__VOID bar = (Func_VOID__VOID )jl_unbox_voidpointer (pbar );
147+ bar ();
148+ checked_eval_string ("bar() = println(\"calling new bar\")" );
149+ bar ();
150+ }
151+
99152 int ret = 0 ;
100153 jl_atexit_hook (ret );
101154 return ret ;
0 commit comments