How to add a built-in module to a C-Python API after Py_Initialize? - python-c-api

I have a module defined in my C code like so:
static struct PyModuleDef module_def = {
PyModuleDef_HEAD_INIT,
"the_module_name", /* m_name */
module_documentation, /* m_doc */
//....
};
and a function to initialize it:
PyMODINIT_FUNC init_the_module(void)
{
PyObject *mod, *submodule;
PyObject *sys_modules = PyThreadState_GET()->interp->modules;
mod = PyModule_Create(&module_def);
PyModule_AddObject(mod, "some_submodule", (submodule = init_the_submodule()));
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
Py_INCREF(submodule);
// more submodules..
return mod;
}
The application that I am embedding python into is quite big and I can not change the workflow much. At this point Py_Initialize has already been called, so I can not call PyImport_ExtendInittabor PyImport_AppendInittab .
How can I create and add the module to the system modules?
Maybe I can manipulate the modules dictionary directly? Like so:
PyObject *modules, *the_module;
modules = PyImport_GetModuleDict();
PyDict_SetItemString(modules, "the_module_name", init_the_module());
the_module = PyDict_GetItemString(modules, "the_module_name"); //this is getting something back
std::cout << PyDict_Size(the_module) << std::endl; // this prints -1

The easiest way to handle this is to statically initialize your statically-linked modules by directly calling initspam() after the call to Py_Initialize() or PyMac_Initialize():
int main(int argc, char **argv)
{
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(argv[0]);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Add a static module */
initspam();
An example may be found in the file Demo/embed/demo.c in the Python source distribution.

Related

[AccelStepper][PlatformIO][mbed] Request for member '' in '', which is of non-class type

so I have been trying to create 3 'accelstepper' objects.
This is a screenshot of my code in case the code section doesn't appear. Also, this is a screenshot of the file "stepper_directory.h"
#include <mbed.h>
#include "stepper_directory.h"
//Include accelstepper library
#include <AccelStepper.h>
//Create accelstepper object for the Z-Axis actuator
AccelStepper zaxis(uint8_t interface = AccelStepper::DRIVER, uint8_t zstep = ZSTEP, uint8_t zdir = ZDIR);
//Create accelstepper object for the theta axis actuator
AccelStepper taxis(uint8_t interface = AccelStepper::DRIVER, uint8_t tstep = TSTEP, uint8_t tdir = TDIR);
//Create accelstepper object for the magnet actuator
AccelStepper maxis(uint8_t interface = AccelStepper::DRIVER, uint8_t mstep = MSTEP, uint8_t mdir = MDIR);
This is the header file i've used "stepper_directory.h"
#ifndef _STEPPER_DIRECTORY
#define _STEPPER_DIRECTORY
#include "PinNames.h"
//Pin Definitions
#define ZSTEP PA_7
#define ZDIR PA_0
#define TSTEP PA_8
#define TDIR PA_1
#define MSTEP PA_9
#define MDIR PA_2
I've tried to setup one stepper in my main code in main.cpp as follows:
int main() {
// put your setup code here, to run once:
zaxis.setMaxSpeed(188000);
while(1) {
// put your main code here, to run repeatedly:
}
}
But the platformIO compiler is throwing out this lines:
src\main.cpp: In function 'int main()':
src\main.cpp:17:7: error: request for member 'setMaxSpeed' in 'zaxis', which is of non-class type 'AccelStepper(uint8_t, uint8_t, uint8_t)
{aka AccelStepper(unsigned char, unsigned char, unsigned char)}'
zaxis.setMaxSpeed(188000);
^~~~~~~~~~~
*** [.pio\build\nucleo_f410rb\src\main.o] Error 1
I have been attempting to search for what is wrong with my object instantiations to no avail. I would really appreciate if there someone could explain what is wrong with this. This is a screenshot of the error in question
The problem is here.
//Create accelstepper object for the Z-Axis actuator
AccelStepper zaxis(uint8_t interface = AccelStepper::DRIVER, uint8_t zstep = ZSTEP, uint8_t zdir = ZDIR);
This is a function declaration. It takes three arguments and returns AccelStepper. You cannot initialize an instance of AccelStepper with this line of code.
I assume AccelStepper's constructor is something like this:
AccelStepper AccelStepper(uint8_t interface, uint8_t zstep, uint8_t zdir);
You can initialize your instance this way:
AccelStepper zaxis(AccelStepper::DRIVER, ZSTEP, ZDIR);

Access to OS functions from CAPL

I'm doing a script using CAPL and am stuck for a solution to grep the login ID from Windows. Could some please help show how to get Windows user login ID from within a CAPL program code, if this is possible?
For example, if the Windows user login ID is 'kp21ml' , I want to read this ID from a CAPL function, as shown below.
byte UserIdCheck()
{
char uid[10];
byte CanMessageTrasmission;
strncpy(uid, xxxx(), 6); // where xxxx() is the unknown OS or system function that could return the login ID ?
if (strncmp(uid, "kp21ml") != 0)
{
write("Access denied!"); // Message to CANoe's Write window
CanMessageTrasmission = 0;
}
else
{
// Access ok
CanMessageTrasmission = 1;
}
return CanMessageTrasmission;
}
I use this CAPL book as my reference guide, which is very good:
http://docplayer.net/15013371-Programming-with-capl.html
But I couldn't find anything to do with system access. I would appreciate your help.
Thanks
Juno
I'm afraid you won't be able to do that directly from a CAPL script.
I generally create a CAPL-DLL and include that in my CANoe project when I need to access some OS level functionality. Though I use it mostly for accessing an external device (e.g. USB) or to interact with another program using sockets over local host, the principle is the same.
You can find more information in CANoe's documentation with examples but the CAPL-DLL source code provided in CANoe samples is a little difficult to understand.
I've attempted to strip some of the "unnecessary" parts in the following code sample; this example will create a CAPL-DLL which "exposes" the multiplyBy10 function and basically allows you to call multiplyBy10 from you CAPL script):
#define USECDLL_FEATURE
#define _BUILDNODELAYERDLL
#pragma warning( disable : 4786 )
#include "cdll.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <map>
char moduleName[_MAX_FNAME];
HINSTANCE moduleHandle;
unsigned int
CAPLEXPORT far CAPLPASCAL multiplyBy10 (unsigned char value)
{
unsigned int result = value * 10;
freopen("CONOUT$", "w", stdout);
std::cout << "multiplyBy10() - value: " << int(value) << ", result: " << result << std::endl;
return (result);
}
CAPL_DLL_INFO4 table[] =
{
{CDLL_VERSION_NAME, (CAPL_FARCALL)CDLL_VERSION, "", "", CAPL_DLL_CDECL, 0xABD, CDLL_EXPORT},
{"multiplyBy10", (CAPL_FARCALL)multiplyBy10, "CAPL_DLL", "This is a demo function", 'L', 1, "D", "", { "value"}},
{0, 0}
};
CAPLEXPORT CAPL_DLL_INFO4 far * caplDllTable4 = table;
bool
WINAPI DllMain(HINSTANCE handle, DWORD reason, void*)
{
static FILE * stream;
switch (reason)
{
case DLL_PROCESS_ATTACH:
{
moduleHandle = handle;
char path_buffer[_MAX_PATH];
DWORD result = GetModuleFileName(moduleHandle, path_buffer, _MAX_PATH);
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath_s(path_buffer, drive, dir, fname, ext);
strcpy_s(moduleName, fname);
AllocConsole();
freopen_s(&stream, "conout$", "w", stdout);
std::cout << "DLL_PROCESS_ATTACH" << std::endl;
return 1;
}
case DLL_PROCESS_DETACH:
{
std::cout << "DLL_PROCESS_DETACH" << std::endl;
FreeConsole();
fclose(stream);
return 1;
}
}
return 1;
}

How to call compat_ioctl or unlocked_ioctl?

I'm trying to implement a driver for RTC (Real Time Clock). I used ioctl function in kernel 2.6.32. It worked fine. But when I run same driver in kernel 3.13.0, it gave an error ‘struct file_operations’ has no member named ‘ioctl’
when I changed ioctl to unlocked_ioctl and compat_ioctl, compiled and moduled inserted.
But calling ioctl in user application not invoking ioctl function in module. What function I have to use in user application to invoke compat_ioctl or unlocked_ioctl?
Check with arguments in driver
define structure file operation Definition like
static struct file_operations query_fops =
{
.owner = THIS_MODULE,
.open = my_open,
.release = my_close,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
.ioctl = my_ioctl
#else
.unlocked_ioctl = my_ioctl
#endif
};
Define ioctl like
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
static int my_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
#else
static long my_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
#endif
{
switch(cmd){
....................................
...................................
}
}
and application level
No need to do any modification you can follow the basic rule for ioctl at application level.

getting libstruct to work in matlab for dll pointer argument

I'm trying to call a dll function in matlab. I have a C++ struct as shown in sixense.h:
typedef struct _sixenseControllerData {
float pos[3];
float rot_mat[3][3];
float joystick_x;
float joystick_y;
float trigger;
...
} sixenseControllerData;
and functions I could call:
SIXENSE_EXPORT int sixenseInit( void );
SIXENSE_EXPORT int sixenseGetAllNewestData( sixenseAllControllerData * );
I can easily get this to work with calllib('sixense','sixenseInit') since there is no input, but for the function sixenseGetAllNewestData I need to have a struct pointer. I realize that libstruct is what I need to use. However, I don't seem to be doing it right.
So I tried libstruct like so:
libstruct('sixenseControllerData')
and I get the error:
??? Error using ==> feval
Undefined function or variable 'lib.sixenseControllerData'.
Error in ==> libstruct at 15
ptr=feval(['lib.' structtype]);
EDIT: here is my current unedited proto file:
http://pastebin.com/PemmmMqF
the full header file is available here:
https://github.com/rll/sixense/blob/master/include/sixense.h
For C structures, loadlibrary generates types named: s_{NAME} where {NAME} is the name of the structure. In your case we create a pointer as:
s = libstruct('s_sixenseControllerData');
We can see this fact by instructing MATLAB to generate a prototype file:
>> loadlibrary('sixense', 'sixense.h', 'proto','sixense_proto')
A prototype file is a file of MATLAB commands which we can modify and use in place of a header file. In this case, the file will contain something like:
sixense_proto.m
...
structs.s_sixenseControllerData.members = struct('pos', 'single#3', 'rot_mat', 'single#9', 'joystick_x', 'single', 'joystick_y', 'single', 'trigger', 'single', 'buttons', 'uint32', 'sequence_number', 'uint8', 'rot_quat', 'single#4', 'firmware_revision', 'uint16', 'hardware_revision', 'uint16', 'packet_type', 'uint16', 'magnetic_frequency', 'uint16', 'enabled', 'int32', 'controller_index', 'int32', 'is_docked', 'uint8', 'which_hand', 'uint8', 'hemi_tracking_enabled', 'uint8');
structs.s_sixenseAllControllerData.members = struct('controllers', 's_sixenseControllerData#4');
....
Unfortunately, a limitation of loadlibrary is that it does not support nested structure very well, especially if a structure contains a pointer to another structure (or an array in this case):
Nested structures or structures containing a pointer to a structure are
not supported. However, MATLAB can access an array of
structures created in an external library.
So you will not be able to directly create the sixenseAllControllerData structure on the MATLAB side, which is defined in the C header file as:
typedef struct _sixenseAllControllerData {
sixenseControllerData controllers[4];
} sixenseAllControllerData;
According to the following discussion, one workaround is to "unroll"/"flatten" the array into separate variables. You can either do this in a copy of the header file, or making the changes in the generated prototype file (which I think is the preferred way). You can do this without having to recompile the shared library.
In your case, change the nested structure in the generated sixense_proto.m file into:
structs.s_sixenseAllControllerData.members = struct(...
'controllers1', 's_sixenseControllerData', ...
'controllers2', 's_sixenseControllerData', ...
'controllers3', 's_sixenseControllerData', ...
'controllers4', 's_sixenseControllerData');
Now we can create a pointer to this structure, and call the C method:
s = libstruct('s_sixenseAllControllerData');
s.controllers1 = libstruct('s_sixenseControllerData');
s.controllers2 = libstruct('s_sixenseControllerData');
s.controllers3 = libstruct('s_sixenseControllerData');
s.controllers4 = libstruct('s_sixenseControllerData');
out = calllib('sixense', 'sixenseGetAllNewestData', s);
get(s)
A completely different solution is to write a MEX-function to interface with the library. It is just like any other C/C++ code, only using mxArray and the MX-API to interface with MATLAB...
Example:
To test the above, I created a simple DLL with similar structures, and implemented the above solution. Here is the code if someone wants to test it:
helper.h
#ifndef HELPER_H
#define HELPER_H
#ifdef _WIN32
#ifdef EXPORT_FCNS
#define EXPORTED_FUNCTION __declspec(dllexport)
#else
#define EXPORTED_FUNCTION __declspec(dllimport)
#endif
#else
#define EXPORTED_FUNCTION
#endif
#endif
mylib.h
#ifndef MYLIB_H
#define MYLIB_H
#include "helper.h"
typedef struct _mystruct {
int pos[3];
double value;
} mystruct;
typedef struct _mystruct2 {
mystruct arr[2];
int num;
} mystruct2;
EXPORTED_FUNCTION void myfunc(mystruct *);
EXPORTED_FUNCTION void myfunc2(mystruct2 *);
#endif
mylib.c
#define EXPORT_FCNS
#include "helper.h"
#include "mylib.h"
void myfunc(mystruct *s)
{
s->pos[0] = 10;
s->pos[1] = 20;
s->pos[2] = 30;
s->value = 4.0;
}
void myfunc2(mystruct2 *s)
{
int i;
for(i=0; i<2; i++) {
myfunc(&(s->arr[i]));
}
s->num = 99;
}
After compiling the above into a DLL, we generate the initial prototype file:
loadlibrary('./mylib.dll', './mylib.h', 'mfilename','mylib_proto')
unloadlibrary mylib
I edit the prototype file as described before:
function [methodinfo,structs,enuminfo,ThunkLibName] = mylib_proto()
MfilePath = fileparts(mfilename('fullpath'));
ThunkLibName = fullfile(MfilePath,'mylib_thunk_pcwin64');
enuminfo = [];
structs = [];
structs.s_mystruct.members = struct('pos','int32#3', 'value','double');
structs.s_mystruct2.members = struct('arr1','s_mystruct', ...
'arr2','s_mystruct', 'num','int32');
ival = {cell(1,0)};
methodinfo = struct('name',ival, 'calltype',ival, 'LHS',ival, ...
'RHS',ival, 'alias',ival, 'thunkname',ival);
methodinfo.thunkname{1} = 'voidvoidPtrThunk';
methodinfo.name{1} = 'myfunc';
methodinfo.calltype{1} = 'Thunk';
methodinfo.LHS{1} = [];
methodinfo.RHS{1} = {'s_mystructPtr'};
methodinfo.thunkname{2} = 'voidvoidPtrThunk';
methodinfo.name{2} = 'myfunc2';
methodinfo.calltype{2} = 'Thunk';
methodinfo.LHS{2} = [];
methodinfo.RHS{2} = {'s_mystruct2Ptr'};
end
Now we can finally invoke functions exposed by the DLL:
%// load library using proto file
loadlibrary('./mylib.dll', #mylib_proto)
%// call first function with pointer to struct
s = struct('pos',[0,0,0], 'value',0);
ss = libstruct('s_mystruct',s);
calllib('mylib', 'myfunc', ss)
get(ss)
%// call second function with pointer to struct containing array of struct
xx = libstruct('s_mystruct2');
xx.arr1 = libstruct('s_mystruct');
xx.arr2 = libstruct('s_mystruct');
calllib('mylib', 'myfunc2', xx)
get(xx)
%// clear references and unload library
clear ss xx
unloadlibrary mylib

Creating Threaded callbacks in XS

EDIT: I have created a ticket for this which has data on an alternative to this way of doing things.
I have updated the code in an attempt to use MY_CXT's callback as gcxt was not storing across threads. However this segfaults at ENTER.
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifndef aTHX_
#define aTHX_
#endif
#ifdef USE_THREADS
#define HAVE_TLS_CONTEXT
#endif
/* For windows */
#ifndef SDL_PERL_DEFINES_H
#define SDL_PERL_DEFINES_H
#ifdef HAVE_TLS_CONTEXT
PerlInterpreter *parent_perl = NULL;
extern PerlInterpreter *parent_perl;
#define GET_TLS_CONTEXT parent_perl = PERL_GET_CONTEXT;
#define ENTER_TLS_CONTEXT \
PerlInterpreter *current_perl = PERL_GET_CONTEXT; \
PERL_SET_CONTEXT(parent_perl); { \
PerlInterpreter *my_perl = parent_perl;
#define LEAVE_TLS_CONTEXT \
} PERL_SET_CONTEXT(current_perl);
#else
#define GET_TLS_CONTEXT /* TLS context not enabled */
#define ENTER_TLS_CONTEXT /* TLS context not enabled */
#define LEAVE_TLS_CONTEXT /* TLS context not enabled */
#endif
#endif
#include <SDL.h>
#define MY_CXT_KEY "SDL::Time::_guts" XS_VERSION
typedef struct {
void* data;
SV* callback;
Uint32 retval;
} my_cxt_t;
static my_cxt_t gcxt;
START_MY_CXT
static Uint32 add_timer_cb ( Uint32 interval, void* param )
{
ENTER_TLS_CONTEXT
dMY_CXT;
dSP;
int back;
ENTER; //SEGFAULTS RIGHT HERE!
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(interval)));
PUTBACK;
if (0 != (back = call_sv(MY_CXT.callback,G_SCALAR))) {
SPAGAIN;
if (back != 1 ) Perl_croak (aTHX_ "Timer Callback failed!");
MY_CXT.retval = POPi;
} else {
Perl_croak(aTHX_ "Timer Callback failed!");
}
FREETMPS;
LEAVE;
LEAVE_TLS_CONTEXT
dMY_CXT;
return MY_CXT.retval;
}
MODULE = SDL::Time PACKAGE = SDL::Time PREFIX = time_
BOOT:
{
MY_CXT_INIT;
}
SDL_TimerID
time_add_timer ( interval, cmd )
Uint32 interval
void *cmd
PREINIT:
dMY_CXT;
CODE:
MY_CXT.callback=cmd;
gcxt = MY_CXT;
RETVAL = SDL_AddTimer(interval,add_timer_cb,(void *)cmd);
OUTPUT:
RETVAL
void
CLONE(...)
CODE:
MY_CXT_CLONE;
This segfaults as soon as I go into ENTER for the callback.
use SDL;
use SDL::Time;
SDL::init(SDL_INIT_TIMER);
my $time = 0;
SDL::Timer::add_timer(100, sub { $time++; return $_[0]} );
sleep(10);
print "Never Prints";
Output is
$
it should be
$ Never Prints
Quick comments:
Do not use Perl structs (SV, AV, HV, ...) outside of the context of a Perl interpreter object. I.e. do not use it as C-level static data. It will blow up in a threading context. Trust me, I've been there.
Check out the "Safely Storing Static Data in XS" section in the perlxs manpage.
Some of that stuff you're doing looks rather non-public from the point of view of the perlapi. I'm not quite certain, though.
$time needs to be a shared variable - otherwise perl works with separate copies of the variable.
My preferred way of handling this is storing the data in the PL_modglobal hash. It's automatically tied to the current interpreter.
We have found a solution to this using Perl interpreter threads and threads::shared. Please see these
Time.xs
Also here is an example of a script using this code.
TestTimer.pl