To load your C shared library, define a class inheriting railgun.SimObject. You need to define four attribute: _clibname_, _clibdir_, _cmembers_ and _cfuncs_.
Note
In this document, yourcode.YourSimObject means the class you need to define. This class is not in RailGun.
Example:
class YourSimObject(SimObject):
_clibname_ = 'name_of_shared_library.so'
_clibdir_ = 'path/to/shared/library'
_cmembers_ = [
'num_i',
'num_j',
'int scalar',
'int vector[i]',
'int matrix[i][j]',
...
]
_cfuncs_ = [
'name_of_c_function',
...
]
def __init__(self, num_i, num_j, **kwds):
SimObject.__init__(self, num_i=num_i, num_j=num_j, **kwds)
def some_function(self, ...):
...
Name of your C shared library.
Path to the directory where your C library locates. If you want to specify relative path from where this python module file are, you can use relpath().
This is a list of the definitions of C variables with the following syntax:
[CDT] VAR_NAME[INDEX] [= DEFAULT]
This let you access the C variable by obj.VAR_NAME.
Starting the name of the member with num_ defines an index whose name is what comes after this. For example, num_i defines index i. Value of num_i is the size of array(s) along the index i. For the member named num_*, you can omit CDT (int).
If the variable is an array, INDEX should be specified. For an array with shape num_i1 x num_i2 x ... x num_iN, INDEX should be [i1][i2]...[iN] or [i1,i2,...,iN].
Warning
The order and number of the variables in _cmembers_ must be the same as in the C struct.
Example:
_cmembers_ = [
'num_i', 'num_j', 'num_k',
'int int_scalar',
'int int_vector1[i]',
'int int_vector2[j] = 0',
'int int_matrix[i][j]',
'double double_scalar = 0.1',
'double double_vector[k] = 18.2',
'double double_matrix[k][i] = -4.1',
]
See also: railgun.cmems()
This is a list of the definitions of C functions with the following syntax:
[RETURN_VAR] FUNC_NAME(ARG, [ARG[, ...]])
Name of C function to be loaded. You don’t need to write the name of the struct. The name of the struct will be automatically prepended.
See also: Loading several C functions at once: func_{key|c1,c2}-notation (choices).
Argument of C function, specified by the following syntax:
CDT_OR_INDEX ARG_NAME [= DEFAULT]
You don’t need to write self which will be automatically passed as the first argument of C function.
Example:
_cfuncs_ = [
"func_spam()",
"bar func_foo()",
"func_with_args(int a, double b, i start=0, i< end=num_i)",
"func_{key | c1, c2, c3}()",
]
See also: Constraints on C functions
This is optional. This is used to specify the name of C struct explicitly:
class CStructName(SimObject): # 'CStructName' is name of c-struct
...
class OtherNameForPyClass(SimObject):
...
_cstructname_ = 'CStructName' # this is name of c-struct
This is optional. This is used to specify the prefix of C functions explicitly (default is name of C Struct + _):
class YourSimObject(SimObject):
...
_cfuncprefix_ = 'MyPrefix'
_cfuncs_ = [
"FuncName()", # 'MyPrefixFuncName' will be loaded
...
]
class YourSimObject(SimObject):
...
_cfuncprefix_ = ''
_cfuncs_ = [
"FuncName()", # 'FuncName' will be loaded
...
]
dict of dict of list, optional.
It defines the subset of C functions and struct variables to be accessible. It must be of the following format:
{'<SUBSET_KEY_1>': {
'funcs': ['<FUNCTION_1>', '<FUNCTION_2>', ...],
'members': ['<MEMBER_1>', '<MEMBER_2>', ...],
'default': True, # optional (default is False)
},
'<SUBSET_KEY_2>': {...},
...}
This is useful when some subset of functions needs some subset of struct members. For example, when in “debugging mode”, you may want to record all temporal variables. However, allocating temporal variables can be wasteful if you are not debugging. Using _cmemsubsets_, you can allocate temporal variables when in the debugging mode and make sure that the functions that requires temporal variables are callable only in the debugging mode. It helps you to avoid segmentation fault due to accessing invalid pointer. _cmemsubsets_ can be thought as machinery for “access levels”.
Here is an example:
class YourSimObject(SimObject):
_cmembers_ = [
# ...
'temp[j][k]',
]
_cfuncs_ = [
'run_{ mode | normal, debug }()',
]
_cmemsubsets_ = {
'debug': {
'funcs': ['run_debug'],
'members': ['temp'],
},
}
# Run simulation in debugging mode:
sim = YourSimObject(..., _cmemsubsets_debug=True)
sim.run(mode='debug')
This is optional. If you want to wrap C function C_FUNC_NAME, define this wrapper function.
Example:
class YourSimObject(SimObject):
_clibname_ = '...'
_clibdir_ = '...'
_cmembers_ = [
'num_i',
'int vec[i]',
]
_cfuncs_ = [
'your_c_function',
]
def _cwrap_your_c_function(old_c_function):
def your_c_function(self, *args, **kwds):
old_c_function(self, *args, **kwds)
return self.vec[:] # return copy
return your_c_function
After your_c_function is loaded from C library, your wrapper function will be called like this:
your_c_function = _cwrap_your_c_function(your_c_function)
This is optional. When C function returns non-zero value, RailGun raises error which just tells the value returned (error code). To make the error message readable, or to handle the error better, you may want to use this attribute.
If C function returns the non-zero value error_code, and it is found _cerrors_, RailGun will raise the error _cerrors_[error_code].
Examples:
class YourSimObject(SimObject):
_clibname_ = '...'
_clibdir_ = '...'
_cmembers_ = [...]
_cfuncs_ = [...]
class YourExceptionClass(Exception):
pass
_cerrors_ = {
# set exception
1: RuntimeError('error code 1 is raised'),
# you can use your own exception class
2: YourExceptionClass('your error message'),
}
New in version 0.1.7.
This is used for setting values of C struct members or any other Python attributes.
The following two lines have same effects:
obj.setv(scalar=1, array=[1, 2, 3])
obj.scalar = 1; obj.array = [1, 2, 3]
You can use alias for elements of array. The following lines have same effect:
obj.setv(var_0_1=1)
obj.var[0][1] = 1
Get the C variable by specifying the name or any other Python attributes.
The following lines have same effect:
var = obj.var
var = obj.getv('var')
This is useful when you want to load multiple variables to local variable at once. The Following lines have same effect:
(a, b, c) = (obj.a, obj.b, obj.c)
(a, b, c) = obj.getv('a', 'b', 'c')
(a, c, c) = obj.getv('a, b, c')
Get the size along index. The Following lines have same effect:
num_i = obj.num_i
num_i = obj.num('i')
You can specify multiple indices. The Following lines have same effect:
(num_i, num_j, num_k) = (obj.num_i, obj.num_j, obj.num_k)
(num_i, num_j, num_k) = obj.num('i', 'j', 'k')
(num_i, num_j, num_k) = obj.num('i, j, k')
To specify C-language type of C struct members and C function arguments, the following C Data Types (CDTs) are available.
CDT | C-language type | numpy dtype | ctypes |
---|---|---|---|
char | char | character | c_char |
short | short | short | c_short |
ushort | unsigned short | ushort | c_ushort |
int | int | int32 | c_int |
uint | unsigned int | uint32 | c_uint |
long | long | int32 or int64 | c_long |
ulong | unsigned long | uint32 or uint64 | c_ulong |
longlong | long long | longlong | c_longlong |
ulonglong | unsigned long long | ulonglong | c_ulonglong |
float | float | float32 | c_float |
double | double | float | c_double |
longdouble | long double | longdouble | c_longdouble |
bool | bool | bool | c_bool |
Note
Numpy dtypes corresponding to CDTs long and ulong are chosen based on the variable returned by platform.architecture().
Enter search terms or a module, class or function name.