SPVM Native APIs is C APIs used in SPVM native method. This document describes the way to define native methods, and shows the all of SPVM Native APIs. If you want to know the list of Native APIs, see L<List of Native APIs|/"List-of-Native-APIs">.
Native method can be written by C language or C++, If the code is compatible withC language or C++(forexample, CUDA/nvcc), it can be compiled into native method. If you see examples of SPVM Native APIs, see L<Examples using SPVM Native APIs|https://github.com/yuki-kimoto/SPVM/tree/master/examples/native>. This contains the examples of C language, C++ and CUDA/nvcc.
=head1 Defintion of SPVM Native Method
=head2 Native Method Declaration
Native Method Declaration is written using Method Descriptor "native"in SPVM module file. SPVM Native Method Declaration ends witha semicolon without Sobroutine Block.
# SPVM/Foo/Bar.spvm
class Foo::Bar {
native static method sum : int($num1: int, $num2: int);
}
=head2 SPVM Native Config File
SPVM Native Config File must be created forSPVM Native Method. The base name without the extension of native config file must be same as SPVM module file and the extension must be ".config".
# Native configuration file for Foo::Bar module
SPVM/Foo/Bar.config
If native configuration file does not exist, an exception occurs.
Native Config File is Perl source code. Native Config File must returnproperly L<Builder::Config|SPVM::Builder::Config> object, otherwise an exception occurs.
Native Method Definition is written in native source file. Native source file is basically C language source file which extension is ".c". This extension can be changed to ".cpp"forC++ source file, or ".cu"forCUDA source file, etc.
# Native source file for Foo::Bar module
SPVM/Foo/Bar.c
The following is natvie source file example written by C language.
Followed by class name "Foo__Bar", which is replaced "::"in Foo::Bar.
Followed by "__".
Followed by method name "sum".
If Native Method Name is invalid, a compile error will occur.
There are two arguments, the first argument is "SPVM_ENV* env"which hasthe information of the execution environment, and the second argument is "SPVM_VALUE* stack"which is used forthe argument and returnvalue.
Native methods are compiled into a shared libraries. teay are shared libraries (.so) on Unix/Linux, dynamic linklibraries (.dll) on Windows or etc corresponding to your os.
The compilation is done whenSPVM is compiled. The build directory must exist, otherwise an exception occures.
The defaultbuild directory is the "~/.spvm_build"directory in the directory containing the executed Perl script, and can be changed withthe environment variable "SPVM_BUILD_DIR".
If you want to useSPVM Native Method from Perl, create a "~/.spvm_build"directory in the directory where the executed Perl script exists.
~/.spvm_build
The generated object files existsunder "work/object"under the build directory. The object file name is the name which the extension of the SPVM module name is changed to ".o".
~/.spvm_build/work/object/Foo/Bar.o
The generated shared libraries existsunder "work/lib"under the build directory. The name of shared library is the name which the extension of the SPVM module name is changed to ".so", or etc corresponding to your os.
# Unix/Linux
~/.spvm_build/work/object/Foo/Bar.so
# Windows
~/.spvm_build/work/object/Foo/Bar.dll
=head2 Stack
The stack is the second argument of the definition of the Native Method. This is called stack. Stack is used getting arguments and returnthe value.
SPVM_VALUE is a union type of C language to store SPVM values. You can save integral value, floating point value, object value, and reference value to it.
For example, to get the value of the first argument(0th) of inttype, writeas follows.
int32_t args0 = stack[0].ival;
For example, to get the value of the second argument(1th) of long type, writeas follows.
int64_t args1 = stack[1].lval;
For example, to returna value of double type, writeas follows.
stack[0].dval = 0.5;
=head2 Getting Arguments
=head3 Get byte type argument
To get the SPVM byte argument, access the bval field. Assign to the C language int8_t type.
int8_t args0 = stack[0].bval;
=head3 Get short type argument
To get the short argument of SPVM, access the sval field. Assign it to the C language int16_t type.
int16_t args0 = stack[0].sval;
=head3 Get inttype argument
To get the SPVM inttype argument, access the ival field. Assign to the C language int32_t type.
int32_t args0 = stack[0].ival;
=head3 Get long type argument
To get the long argument of SPVM, access the lval field. Assign to the C language int64_t type.
int64_t args0 = stack[0].lval;
=head3 Get float type argument
To get the SPVM float type argument, access the fval field. Assign to float type of C language.
float args0 = stack[0].fval;
=head3 Get double type argument
To get the SPVM double argument, access the dval field. Assign to the C language double type.
double args0 = stack[0].dval;
=head3 Get object type argument
To get the SPVM object type argument, access the oval field. Assign it to void* type in C language.
void* args0 = stack[0].oval;
=head3 Get byte Reference Type Argument
If you get SPVM byte Reference Type argument, use"bref"field. it can be assinged to the value of C language int8_t* type.
int8_t* args0 = stack[0].bref;
=head3 Get short Reference Type Argument
If you get SPVM short Reference Type argument, use"sref"field. it can be assinged to the value of C language int16_t* type.
int16_t* args0 = stack[0].sref;
=head3 Get intReference Type Argument
If you get SPVM intReference Type argument, use"iref"field. it can be assinged to the value of C language int32_t* type.
int32_t* args0 = stack[0].iref;
=head3 Get long Reference Type Argument
If you get SPVM long Reference Type argument, use"lref"field. it can be assinged to the value of C language int64_t* type.
int64_t* args0 = stack[0].lref;
=head3 Get float Reference Type Argument
If you get SPVM float Reference Type argument, use"fref"field. it can be assinged to the value of C language float* type.
float* args0 = stack[0].fref;
=head3 Get double Reference Type Argument
If you get SPVM double Reference Type Argument, use"dref"field. it can be assinged to the value of C language double* type.
double* args0 = stack[0].dref;
=head3 Get multiple numeric type arguments
In a Native Method, multiple numeric type arguments are assigned to the coresponding multiple arguments.
For example, In the case of the argument valuesof L<Complex_2d|SPVM::Complex_2d> type, you can get them by the following way.
double args_re = stack[0].dval;
double args_im = stack[1].dval;
Note that you cannot access the valuesby the field name of L<Complex_2d|SPVM::Complex_2d>.
=head2 Return Value
=head3 Set returnvalue of byte type
Use C<bval> field of C<SPVM_VALUE> to set a returnvalue which type of SPVM is C<byte>. This is corresponding to C<int8_t> type of C language.
int8_t retval;
stack[0].bval = retval;
=head3 Set returnvalue of short type
Use C<sval> field of C<SPVM_VALUE> to set a returnvalue which type of SPVM is C<short>. This is corresponding to C<int16_t> type of C language.
int16_t retval;
stack[0].sval = retval;
=head3 Set returnvalue of inttype
Use C<ival> field of C<SPVM_VALUE> to set a returnvalue which type of SPVM is C<int>. This is corresponding to C<int32_t> type of C language.
int32_t retval;
stack[0].ival = retval;
=head3 Set long type returnvalue
Use C<lval> field of C<SPVM_VALUE> to set a returnvalue which type of SPVM is C<long>. This is corresponding to C<int64_t> type of C language.
int64_t retval;
stack[0].lval = retval;
=head3 Set returnvalue of float type
Use C<fval> field of C<SPVM_VALUE> to set a returnvalue which type of SPVM is C<float>. This is corresponding to C<float> type of C language.
float retval;
stack[0].fval = retval;
=head3 Set returnvalue of double type
Use C<dval> field of C<SPVM_VALUE> to set a returnvalue which type of SPVM is C<double>. This is corresponding to C<double> type of C language.
double retval;
stack[0].dval = retval;
=head3 Set returnvalue of object type
Use C<oval> field of C<SPVM_VALUE> to set a returnvalue which type of SPVM is object. This is corresponding to C<void*> type of C language.
void* retval;
stack[0].oval = retval;
=head3 Set multiple numeric returnvalue
If you set multiple numeric returnvalue in native method, set multiple returnvalues.
For example, in the case of L<Complex_2d|SPVM::Complex_2d>, dothe following.
double retval_x;
double retval_y;
stack[0].dval = retval_x;
stack[1].dval = retval_y;
=head2 Call SPVM Method
If you want to call a method, you get a method id using L<get_class_method_id|"get_class_method_id"> or L<get_instance_method_id|"get_instance_method_id">.
L<get_class_method_id|"get_class_method_id"> get a method id of a class method.
L<get_instance_method_id|"get_instance_method_id"> get a method id of a instance method.
Nonzero ifthe method raised an exception, 0 ifnoexception occurred.
The returnvalue of the method is stored in the first element of the stack.
int32_t total = stack[0].ival;
=head2 Native Method Scope
Native method are entirely enclosed in scope.
Objects added to the mortal stack will automatically have their reference count decremented by 1 whenthe Native Method ends. When the reference count reaches 0, it is released.
Use push_mortal to add objects to the mortal stack.
env->push_mortal(env, object);
Native APIs that normally create an object such as "new_object"will add the automatically created object to the mortal stack so you don't need to usethis.
Use "enter_scope"to create a scope. The returnvalue is the ID of that scope.
int32_t scope_id = env->enter_scope (env);
Use "leave_scope"to leave the scope. For the argument, it is necessary to specify the scope ID obtained in "enter_scope".
env->leave_scope(env, scope_id);
Use "remove_mortal"to remove the object from the mortal stack. For the argument, specify the scope ID obtained by "enter_scope"and the object you want to remove. The object is removed from the mortal stack and the reference count is automatically decremented by 1. When the reference count reaches 0, it is released.
env->remove_mortal(env, scope_id, object);
Information about the mortal stack is stored in env.
=head2 Exception in Native Method
In the Native Method, it is the returnvalue that indicates whether an exception hasoccurred.
return0;
return1;
If noexception occurs, "0"is returned. This is definedas "0".
If an exception occurs, "1"is returned. It is definedas a value other than "0".
If you want to set the exception message yourself, you can create an exception message with"new_string_nolen"and set it with"set_exception".
If noexception message is set, a defaultexception message will be set.
Usually, L<die|"die""> is definedto make it easier to use, so it is better to usethis.
returnenv->die("Error. Values must be %d and %d", 3, 5, "Foo/Bar.c", __LINE__);
L<die|"die""> can be used in the same way as the C language sprintffunction. Be sure to include this file name in the second from the end, and the line number in the lastargument. If the message exceeds 255 bytes, the excess is truncated.
The exception is stored in env.
=head2 Pointer Type
There is a type called pointer type in SPVM, but I will explain how to useit.
The pointer type definition specifies the pointer_t descriptor in the SPVM class definition. Pointer types cannot have field definitions. This example describes how to usethe C standard "struct tm"as a pointer type.
# SPVM/MyTimeInfo.spvm
class MyTimeInfo : pointer_t {
# Constructor
native static method new : MyTimeInfo ();
# Get second
native method sec : int();
# Destructor
native method DESTROY : ();
}
It defines a new constructor, a method that takes seconds information called sec, and a destructor called DESTROY. These are Native Method.
In the constructor new, the memory of "struct tm"is first allocated by the alloc_memory_block_zero function. This is a function that reserves one memory block in SPVM. Similar to malloc, this function increments the memory block count by one, making it easier to spot memory leaks.
If you returnthis as a returnvalue, the constructor is complete.
stack[0].ival = tm_ptr-> tm_sec;
return0;
Next, let's get the value of tm_sec. sec method. The get_pointer function can be used to get a pointer to the memory allocated as a "struct tm"from a pointer type object.
Execute the free_memory_block function to free the memory. Be sure to free the memory allocated by alloc_memory_block_zero withthe free_memory_block function. Releases the memory and decrements the memory block count by one.
=head2 Call Native API
Native API can be called from "SPVM_ENV* env"passed as an argument. Note that you have to pass env as the first argument.
Get the class variable ID giventhe class name, class variable name and signature. If the class variable does not exist, a value less than 0 is returned.
The signature is the same as the class variable type name.
Do the same as C<new_object_raw>, and add the created object to the mortal stack of the environment. Use this function in normal useinstead of C<new_object_raw>.
Do the same as C<new_byte_array_raw>, and add the created array to the mortal stack of the environment. Use this function in normal useinstead of C<new_byte_array_raw>.
Do the same as C<new_short_array_raw>, and add the created array to the mortal stack of the environment. Use this function in normal useinstead of C<new_short_array_raw>.
Do the same as C<new_int_array_raw>, and add the created array to the mortal stack of the environment. Use this function in normal useinstead of C<new_int_array_raw>.
Do the same as C<new_long_array_raw>, and add the created array to the mortal stack of the environment. Use this function in normal useinstead of C<new_long_array_raw>.
Do the same as C<new_float_array_raw>, and add the created array to the mortal stack of the environment. Use this function in normal useinstead of C<new_float_array_raw>.
Do the same as C<new_double_array_raw>, and add the created array to the mortal stack of the environment. Use this function in normal useinstead of C<new_double_array_raw>.
Create a new object type array by specifying the basic type ID and the array length. The basic type ID must be the correct basic type ID got by C<get_basic_type_id> function.
Do the same as C<new_object_array_raw>, and add the created array to the mortal stack of the environment. Use this function in normal useinstead of C<new_object_array_raw>.
Create a new multi dimension array by specifying the basic type ID, the type dimension of the element, and the array length. The basic type ID must be the correct basic type ID got bu C<get_basic_type_id> function. the type dimension of the element must be less than or equals to 255.
Do the same as C<new_muldim_array_raw>, and add the created array to the mortal stack of the environment. Use this function in normal useinstead of C<new_muldim_array_raw>.
Create a new multi-numeric array by specifying the basic type ID and the array length. The basic type ID must be the correct basic type ID got by C<basic_type_id> function.
Do the same as C<new_mulnum_array_raw>, and add the created array to the mortal stack of the environment. Use this function in normal useinstead of C<new_mulnum_array_raw>.
Do the same as C<new_string_nolen_raw>, and add the created string object to the mortal stack of the environment. Use this function in normal useinstead of C<new_string_nolen_raw>.
Do the same as C<new_string_raw>, and add the created string object to the mortal stack of the environment. Use this function in normal useinstead of C<new_string_raw>.
Create a pointer type object by specifying a basic type ID and a C language pointer. The basic type ID must be the correct basic type ID got by C<get_basic_type_id> function.
Do the same as C<new_pointer_raw>, and add the created string object to the mortal stack of the environment. Use this function in normal useinstead of C<new_pointer_raw>.
Do the same as C<concat_raw>, and add the created string object to the mortal stack of the environment. Use this function in normal useinstead of C<concat_raw>.
If you specify a byte[] type exception message and a class name, method name, file name and line number, the character string of the class name, method name, file name and line number is added to the end of the byte[] type exception message. The added character string will be returned.
This function does not add objects to the mortal stack, usenew_stack_trace to avoid memory leaks fornormal use.
When a byte[] type exception message and a class name, method name, file name and line number are specified, the string of the class name, method name, file name and line number is added to the end of the string type exception message. Returns a new string type object. Add the newly created object to the mortal stack.
=head2 length
int32_t (*length)(SPVM_ENV*, void* array);
If you specify an array, the lengthof the array is returned.
If you specify an array of object type and methodscript and element objects, the element object is assigned to the corresponding methodscript position. If the element's object hasa weak reference, the weak reference is removed. The reference count of the originally assigned object is decremented by 1.
If an object and field ID are specified, the byte field value will be returned as a C language int8_t type value. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID, the value of the short type field will be returned as the int16_t type value of C language. The field ID must be a valid field ID obtained withthe field_id function.
If an object and a field ID are specified, the value of the inttype field will be returned as a C language int32_t type value. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID, the value of the long type field will be returned as the value of int64_t type of C language. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID, the value of the float type field will be returned as a C language float type value. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID, the value of the double type field will be returned as a double type value in C language. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID, the value of the object type field is returned as a void* type value in C language. The field ID must be a valid field ID obtained withthe field_id function. If the field is a weak reference, it will be removed.
If you specify the object and field ID and the value of the field, the value is set to the byte type field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the short type field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the inttype field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the long type field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the float type field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the double type field. The field ID must be a valid field ID obtained withthe field_id function.
Object and field Specify the ID and the value of the field and set the value to the object type field. The field ID must be a valid field ID obtained withthe field_id function. After setting, the reference count is incremented by 1. The original value hasthe reference count decremented by 1.
If an object and a class variable ID are specified, the value of the byte type class variable is returned as a C language int8_t type value. The class variable ID must be a valid class variable ID obtained withthe field_id function.
If an object and a class variable ID are specified, the value of the short type class variable will be returned as a C language int16_t type value. The class variable ID must be a valid class variable ID obtained withthe field_id function.
If an object and a class variable ID are specified, the value of the inttype class variable will be returned as a C language int32_t type value. The class variable ID must be a valid class variable ID obtained withthe field_id function.
If an object and a class variable ID are specified, the value of the long type class variable will be returned as a C language int64_t type value. The class variable ID must be a valid class variable ID obtained withthe field_id function.
If an object and a class variable ID are specified, the value of the float type class variable will be returned as a C language float type value. The class variable ID must be a valid class variable ID obtained withthe field_id function.
If you specify an object and a class variable ID, the value of the double type class variable is returned as a C type double type value. The class variable ID must be a valid class variable ID obtained withthe field_id function.
When an object and a class variable ID are specified, the value of the object type class variable is returned as a C language void* type value. The class variable ID must be a valid class variable ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the byte type field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the short type field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the inttype field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the long type field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the float type field. The field ID must be a valid field ID obtained withthe field_id function.
If you specify the object and field ID and the value of the field, the value is set to the double type field. The field ID must be a valid field ID obtained withthe field_id function.
Object and field Specify the ID and the value of the field and set the value to the object type field. The field ID must be a valid field ID obtained withthe field_id function. After setting, the reference count is incremented by 1. The original value hasthe reference count decremented by 1.
Specify a scope ID to exitthat scope and decrement the object's reference count stored in the mortal stack. Objects witha reference count of 0 are released. The scope ID must be the ID obtained by the enter_scope function.
Given an object and a base type ID and a type dimension, returns a nonzero value ifthe object matches both the base type ID and the type dimension, and 0 otherwise.
If you specify the size in bytes, the memory block is allocated and the pointer of the allocated memory block is returned. If fail to alloc memory, returnNULL. If success, all bits in the memory block are initialized with0 and the memory block count (memory_blocks_count)is incremented by 1.
The memory block is increased by 1 whenan object is created, whenthe alloc_memory_block_zero function is called, and whena back reference is added by the weaken function.
Basic type ID of any object type. This is used internally.
=head2 dump_raw
void* (*dump_raw)(SPVM_ENV* env, void* object);
Get the string which dumpthe object. The string is the same as the returnvalue of C<dump> operator.
=head2 dump
void* (*dump)(SPVM_ENV* env, void* object);
Do the same as C<dump_raw>, and add the created string object to the mortal stack of the environment. Use this function in normal useinstead of C<dump_raw>.
Get a instance method ID by the class name, the method name, and the method signature. If the instance method does not exists, a negative value is returned.
Native APIs have indexes which correspond to the names. These indexes are permanently same forthe binary compatibility. When a new Native API is added, it will be added to the end.