A native class is the class implemented by a native language such as the C language and C++.
=head1 Native Method Definition
A native method is definedby L<native method attribute|SPVM::Document::Language::Class/"Method Attributes"> in an SPVM class file. It ends witha semicolon. A native method does not have its block.
# SPVM/MyClass.spvm
class MyClass {
native static method sum : int($num1: int, $num2: int);
}
=head1 Native Config File
A native config file is needed fora native class. The name of the config file is the same as the SPVM class name, but the extension C<.spvm> is replaced withC<.config>.
# The name of a native config file
SPVM/MyClass.config
A native config file is writen by Perl. It must end witha L<Builder::Config|SPVM::Builder::Config> object.
A config file is executed by Perl's L<do|https://perldoc.perl.org/functions/do> function. The returned L<Builder::Config|SPVM::Builder::Config> object is used as the config fora native class.
Exceptions:
If the native config file does not exist, an exception is thrown.
A config file must end witha L<Builder::Config|SPVM::Builder::Config> object. Otherwise, an exception is thrown.
A native class is the class implemented by a native language such as the C language and C++.
The name of the native class file is the same as the SPVM class name, but the extension C<.spvm> is replaced withC<.> and L<extension of the native class|/"Native Class File Extension">.
SPVM/MyClass.c
=head2 Native Class File Extension
The file extension of a native class is definedby L<Builder::Config#ext|SPVM::Builder::Config/"ext"> field in a config file.
Examples:
$config->ext('c');
$config->ext('cpp');
$config->ext('cc');
$config->ext('cu');
Exceptions:
If L<ext|SPVM::Builder::Config/"ext"> is defined, but its corresponding config file does not exist, an exception is thrown.
=head2 Native Function
A native function is a function definedin a native class.
A native function must have the name following the rules below.
=over 2
=item * 1. Starts withC<SPVM__>.
=item * 2. Followed by the SPVM class name, but C<::> is replaced withC<__>.
=item * 3. Followed by C<__>.
=item * 3. Followed by the name of the method.
=back
Exceptions:
If the name of a native function is invalid, an exception is thrown.
Examples:
For example, ifthe class is C<MyClass::Math> and the method name is C<sum_value>, the name of the native function is C<SPVM__MyClass__Math__sum_value>.
The first argument C<env> is the current L<runtime environment|/"Runtime Environment">. This is the pointer to a value of C<SPVM_ENV> type.
The second argument C<stack> is the current L<runtime stack|/"Runtime Stack">. This is is the pointer to the valuesof L<SPVM_VALUE|/"SPVM_VALUE Type"> type.
The arguments givento this native function have been stored in the runtime stack.
See L</"Getting Argument"> to get the valuesof the arguments.
=head2 Native Function Return Value
A native function must returna value of the C<int32_t> type.
method foo ($args0: int, $args1: Point, $arg2: Complex_2d);
Do the following using the C<ival> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of $args0which type is inttype.
int32_t args0 = stack[0].ival;
Do the following using the C<oval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of $args1which type is L<Point|SPVM::Point> type.
int64_t args1 = stack[1].oval;
Do the following to get the valuesof $args2which type is L<Complex_2d|SPVM::Complex_2d> multi-numeric type.
double args2_re = stack[2].dval;
double args2_im = stack[3].dval;
Note that the valuesof the multi-numeric type have been stored in the multiple valuesin the runtime stack. The lengthof the value in the runtime stack is the same as the lengthof the fields of the multi-numeric type.
=head3 Getting byte Type Argument
Use the C<bval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of the SPVM C<byte> type from an argument.
int8_t args0 = stack[0].bval;
=head3 Getting short Type Argument
Use the C<sval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of the SPVM C<short> type from an argument.
int16_t args0 = stack[0].sval;
=head3 Getting intType Argument
Use the C<ival> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of the SPVM C<int> type from an argument.
int32_t args0 = stack[0].ival;
=head3 Getting long Type Argument
Use the C<lval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of the SPVM C<long> type from an argument.
int64_t args0 = stack[0].lval;
=head3 Getting float Type Argument
Use the C<fval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of the SPVM C<float> type from an argument.
float args0 = stack[0].fval;
=head3 Getting double Type Argument
Use the C<dval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of the SPVM C<double> type from an argument.
double args0 = stack[0].dval;
=head3 Getting Object Type Argument
Use the C<oval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of an SPVM object type from an argument.
void* args0 = stack[0].oval;
=head3 Getting byte Reference Type Argument
Use the C<bref> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of an SPVM C<byte> reference type from an argument.
int8_t* args0 = stack[0].bref;
=head3 Getting short Reference Type Argument
Use the C<sref> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of an SPVM C<short> reference type from an argument.
int16_t* args0 = stack[0].sref;
=head3 Getting intReference Type Argument
Use the C<iref> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of an SPVM C<int> reference type from an argument.
int32_t* args0 = stack[0].iref;
=head3 Getting long Reference Type Argument
Use the C<lref> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of an SPVM C<long> reference type from an argument.
int64_t* args0 = stack[0].lref;
=head3 Getting float Reference Type Argument
Use the C<fref> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of an SPVM C<float> reference type from an argument.
float* args0 = stack[0].fref;
=head3 Getting double Reference Type Argument
Use the C<dref> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to get the value of an SPVM C<double> reference type from an argument.
double* args0 = stack[0].dref;
=head3 Getting Multi-Numeric Type Arguments
The valuesof an SPVM multi-numeric type from an argument have been stored to the multiple valuesin L<runtime stack|/"Runtime Stack">. the lengthof the valuesin the runtime stack is the same as the lengthof the fields of the SPVM multi-numeric type.
For example, ifthe argument type is L<Complex_2d|SPVM::Complex_2d> type, these valueshave been stored to multiple fields the multiple valuesin the runtime stack.
double args0_re = stack[0].dval;
double args0_im = stack[1].dval;
=head2 Return Value
If the reutrn type of an SPVM method is not the C<void> type, the first argument of L<runtime stack|/"Runtime Stack"> must be set to a returnvalue.
int32_t return_value = 5;
stack[0].ival = return_value;
=head3 Setting Return Value of byte Type
Use the C<bval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to set a returnvalue of the SPVM C<byte> type.
stack[0].bval = return_value;
=head3 Setting Return Value of short Type
Use the C<sval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to set a returnvalue of the SPVM C<short> type.
stack[0].sval = return_value;
=head3 Setting Return Value of intType
Use the C<ival> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to set a returnvalue of the SPVM C<int> type.
stack[0].ival = return_value;
=head3 Setting Return Value of long Type
Use the C<lval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to set a returnvalue of the SPVM C<long> type.
stack[0].lval = return_value;
=head3 Setting Return Value of float Type
Use the C<fval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to set a returnvalue of the SPVM C<float> type.
stack[0].fval = return_value;
=head3 Setting Return Value of double Type
Use the C<dval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to set a returnvalue of the SPVM C<double> type.
stack[0].dval = return_value;
=head3 Setting Return Value of Object Type
Use the C<oval> field of L<SPVM_VALUE|/"SPVM_VALUE Type"> type to set a returnvalue of an SPVM object type.
stack[0].oval = return_value;
=head3 Setting Return Value of Multi-Numeric Type
Multiple valuesin L<runtime stack|/"Runtime Stack"> are needed to be set to valuesof the field type of the multi-numeric type. The lengthof the valuesin the runtime stack is the same as the lengthof the fields of the SPVM multi-numeric type.
There is an example in the case that the returntype is L<Complex_2d|SPVM::Complex_2d>.
double return_value_x;
double return_value_y;
stack[0].dval = return_value_x;
stack[1].dval = return_value_y;
=head2 Native APIs
L<Native APIs|SPVM::Document::NativeAPI> are the APIs written by the C language forSPVM operations. Native APIs can be called in native classes.
If a native method throws an exception, the native function must returna non-zero value, normally the basic type ID of an error class.
A message can be set to L<exception variable|SPVM::Document::Language::ExceptionHandling/"Exception Variable">. If nomessage is set to L<exception variable|SPVM::Document::Language::ExceptionHandling/"Exception Variable">, a defaultexception message is set to it.
env->set_exception(env, stack, env->new_string_nolen(env, stack, "An exception is thrown."));
returnSPVM_NATIVE_C_BASIC_TYPE_ID_ERROR_CLASS;
L<die|SPVM::Document::NativeAPI/"die"> native API can be used to throw an exception easily.
returnenv->die("The value must be %d.", 3, __func__, FILE_NAME, __LINE__);
=head2 Pointer Class
An SPVM object can have a L<pointer value|/"Pointer Value">.
If necessary, you can mark a class as a pointer class using L<pointer class attribute|SPVM::Document::Language::Class/"Class Attributes">.
An object can have a pointer value. A pointer value is the address of a C/C++ object.
See L<get_pointer|SPVM::Document::NativeAPI/"get_pointer"> native API to get a pointer value of an object.
See L<set_pointer|SPVM::Document::NativeAPI/"set_pointer"> native API to set a pointer value of an object.
=head2 Native Directory
A native directory is the directory fornative header files and native source files.
The name of the native directory is the same as the SPVM class name, but the extension C<.spvm> is replaced withC<.native>.
# The name of a native directory
SPVM/MyClass.native
=head3 Native Header Files
A native class can include native header files in the C<include> directory under the native directory.
# Native header files
SPVM/MyClass.native/include/foo.h
/dir/bar.h
// Native class
#include "foo.h"
#include "dir/bar.h"
=head3 Native Source Files
A native class can compile native source files in the C<src> directory under the native directory using L<add_source_file|SPVM::Builder::Config/"add_source_file"> in C<SPVM::Builder::Config> class.
# Native source files
SPVM/MyClass.native/src/foo.c
/dir/bar.c
# Native config file
my@source_files= ("foo.c", "dir/bar.c");
$config->add_source_file(@source_files);
=head2 Scope
A native function hasits scope.
L<enter_scope|SPVM::Document::NativeAPI/"enter_scope"> native API is called beforethe call of the native function.
L<leave_scope|SPVM::Document::NativeAPI/"leave_scope"> native API is called afterthe call of the native function.
You can create a scope and pushobjects to the L<native mortal stack|/"Native Mortal Stack">.
A runtime stack is created fora native thread. An SPVM runtime creates a runtime stack forthe main thread.
A runtime stack is used to get valuesof arguments and returna value, and it also stored its own data such as L<exception variable|SPVM::Document::Language::ExceptionHandling/"Exception Variable">.
This is the pointer to the valuesof L<SPVM_VALUE|/"SPVM_VALUE Type"> type, normally named C<stack>.
SPVM_VALUE* stack;
A runtime stack is givento the second argument of a native function.
A runtime stack can be created and freed using L<new_stack|SPVM::Document::NativeAPI/"new_stack"> native API and L<free_stack|SPVM::Document::NativeAPI/"free_stack"> native API.
=head2 Arguments Width
The width of the arguments is the lengthin units of L<SPVM_VALUE|/"SPVM_VALUE Type"> type.
If the type is a multi-numeric type, the width of the arguments is the lengthof the fields of the multi-numeric type. Otherwise, it is 1.
Consider the following method definition.
method foo ($args0: int, $args1: Point, $arg2: Complex_2d);
The argument width of the C<int> type is 1.
The argument width of the object type L<Point|SPVM::Point> is 1.
The argument width of the multi-numeric type L<Complex_2d|SPVM::Complex_2d> is the lengthof its field. It is 2.
So the width of the arguments is totally 4.
=head2 Native Motal Stack
A native mortal stack is a stack that is used by L<enter_scope|SPVM::Document::NativeAPI/"enter_scope"> native API and L<leave_scope|SPVM::Document::NativeAPI/"leave_scope"> native API.
A L<runtime stack|/"Runtime Stack"> hasone native mortal stack.
=head2 Compilation and Link
A native class and native source files are compiled to object files and are linked and a shared library is generated.
The extension of a shared library is C<.so> in Linux and UNIX, C<.dylib> in Mac, C<.dll> in Windows.
L<SPVM_BUILD_DIR|SPVM::Document::EnvironmentVariables/"SPVM_BUILD_DIR"> environment variable must be set to a build directoy path.
Normally, C<~/.spvm_build> is set to it.
~/.spvm_build
Object files and a shared library file are output to the build directory.
If the build directory does not exist, it is created.
Exceptions:
A string of non-zero lengthmust be set to L<SPVM_BUILD_DIR|SPVM::Document::EnvironmentVariables/"SPVM_BUILD_DIR"> environment variable. Otherwise, an exception is thrown.
=head2 Dependency Resolution
The dependencies of compilation and linkof a L<native class|/"Native Class">, L<native header files|/"Native Header Files">, and L<native source files|/"Native Source Files"> are resolved by the following rules.
=over 2
=item * If the version of SPVM is newer, the compilation and the linkare performed.
=item * If the modification timeof a native config file is newer than the generated dynamic library, the compilation and the linkare performed.
=item * If the max of the modification timeof the object files generated by compiliation is newer than the generated dynamic library, the linkis performed.
=item * If the modification timeof a native class is newer than the object file generated from the native class, the compilation is performed.
=item * If the modification timeof a native source file is newer than the generated object file, the compilation is performed.
=item * If the max of the modification timeof header source files is newer than the object file generated from a native source file, the compilation of the native source file is performed.
=back
If L<SPVM::Builder::Config#force|SPVM::Builder::Config/"force"> field is set to 1, the compilation and the link are forced.
$config->force(1);
=head1 Resource
A native class can usenative header files and native source files writen by native langauges such as the C language and C++ using L<SPVM::Builder::Config#use_resource|SPVM::Builder::Config/"use_resource">.
# MyClass.config
$config->use_resource("Resource::Zlib");
// MyClass.c
#include "zlib.h"
For details, see L<SPVM::Document::Resource>.
=head1 Distribution
A distribution fora native class can be generated by L<spvmdist> command.
# C
spvmdist --native c --user-name="Yuki Kimoto"--user-email="kimoto.yuki@gmail.com"MyNativeClass
# C++
spvmdist --native c++ --user-name="Yuki Kimoto"--user-email="kimoto.yuki@gmail.com"MyNativeClass
A native class file and a config file only can be added to an existing distribution.
# C
spvmdist --only-lib-files --native c --user-name="Yuki Kimoto"--user-email="kimoto.yuki@gmail.com"MyNativeClass lib
# C++
spvmdist --only-lib-files --native c++ --user-name="Yuki Kimoto"--user-email="kimoto.yuki@gmail.com"MyNativeClass lib