I' m trying to import a .so library into a python code to use c functions. I think using
from ctypes import *
import ctypes
lib = CDLL('./libcaenhvwrapper.so.5.56')
is working fine. I need to use some user defined types which are defined in a header file
but I cannot access them.
thank you in advance
The types are not in the .so file that the ctypes module loads.
C types don't work like that, they're declared in the header and you must have the header to use a (C) library, even from C.
You're going to have to use the various ctypes APIs to re-create the types in Python. See this part of the tutorial, for instance, for how to work with struct and union types.
Now my code works with a normal c library, but I need to use a .so library from Caen and I
get Segmentation fault. This is the code:
from ctypes import *
lib = CDLL('./libcaenhvwrapper.so.5.56')
lib.CAENHVInitSystem.restype = c_int
lib.CAENHVInitSystem.argtypes = [c_int, c_int, c_char_p, c_char_p, c_char_p]
lib.CAENHVGetError.restype = c_int
CAENHV_SYSTEM_TYPE_t = c_int
sy1527 = CAENHV_SYSTEM_TYPE_t(0)
sy2527 = CAENHV_SYSTEM_TYPE_t(1)
sy4527 = CAENHV_SYSTEM_TYPE_t(2)
sy5527 = CAENHV_SYSTEM_TYPE_t(3)
n568 = CAENHV_SYSTEM_TYPE_t(4)
v65xx = CAENHV_SYSTEM_TYPE_t(5)
n1470 = CAENHV_SYSTEM_TYPE_t(6)
v8100 = CAENHV_SYSTEM_TYPE_t(7)
link = c_int
LINKTYPE_TCPIP = link(0)
LINKTYPE_RS232 = link(1)
LINKTYPE_CAENET = link(2)
LINKTYPE_USB = link(3)
LINKTYPE_OPTLINK = link(4)
LINKTYPE_USB_VCP = link(5)
string15=c_char*15
address=string15('1','3','7','.','1','3','8','.','1','3','.','2','0','3','\0')
userName = c_char_p('user')
passwd = c_char_p('user')
ret_init = lib.CAENHVInitSystem(0, 0, address, userName, passwd)
when I try to call the function I get a segmentation fault. I think the types are correctly defined.
Below you can see a piece of code which works ok.
from ctypes import *
lib2 = CDLL('/lib64/libc.so.6')
string15=c_char*15
address=string15('1','3','7','.','1','3','8','.','1','3','.','2','0','3','\0')
address1=create_string_buffer('137.138.13.203')
address2=c_char_p('137.138.13.200')
userName = c_char_p('user')
passwd = c_char_p('user')
a= lib2.strncmp(address, userName, c_int(4))
a= lib2.strncmp(userName, address, 4)
a= lib2.strncmp(address2, address, 15)
lib2.printf('%d\n', ret_init)
lib2.printf('%s\n', address)
lib2.printf('%s\n', address1)
lib2.printf('%s\n', address2)
lib2.printf('%d\n', lib2.strlen(address))
lib2.printf('%d\n', lib2.strlen(address1))
lib2.printf('%d\n', lib2.strlen(address2))
Related
I am calling some c-sdk from python code. This python code is running as lambda on greengrass. I am using cffi to call the function of shared so from python. My lambda (python code) is running as gcc_user but when i print the user in my C code, it prints something like: T� Pp.
Below is the C code that i am using to print the user info:
char* username[10];
getlogin_r(username, 10);
printf("current user in c program ");
for(index = 0;index<10; index++)
{
printf("%c",username[index]);
}
printf("\n");
Below is the python code that i am using call the shared lib (C code):
import cffi
import _cffi_backend
from sys import exit, platform
import boto3
from multiprocessing import Process
import sys, os
import logging
import getpass
def StartVideoStreaming(channelName):
ffi = cffi.FFI()
cdef_from_file = None
header = '/home/admin/alprwebrtcdemo/amazon-kinesis-video-streams-webrtc-sdk-c/samples/kvsWebRTCClientMasterGstreamer.h'
try:
with open(header, 'r') as libtestcffi_header:
cdef_from_file = libtestcffi_header.read()
except FileNotFoundError:
print('Unable to find "%s"' % header)
exit(2)
except IOError:
print('Unable to open "%s"' % header)
exit(3)
finally:
if cdef_from_file == '':
print('File "%s" is empty' % header)
exit(1)
ffi.cdef(cdef_from_file)
lib_extension = ''
if platform.startswith('freebsd') or platform.startswith('linux'):
lib_extension = 'so'
elif platform.startswith('win'):
lib_extension = 'dll'
CLibTC = ffi.dlopen('/home/admin/alprwebrtcdemo/amazon-kinesis-video-streams-webrtc-sdk-c/build/liblibkvsWebrtcClientMasterGstSample.' + lib_extension)
arg_0 = "arg0".encode('utf-8')
arg_1 = channelName.encode('utf-8')
argv_keepalive = [ffi.new("char[]", arg_0),
ffi.new("char[]", arg_1)]
argv = ffi.new("char *[]", argv_keepalive)
session = boto3.Session()
logging.info("user in process: {}".format(getpass.getuser()))
credentials = session.get_credentials()
accountKeyID = credentials.access_key
accountSecret = credentials.secret_key
sessionToken = credentials.token
logging.info("ID: {}, secret: {}, session: {}".format(accountKeyID, accountSecret, sessionToken))
arg1 = accountKeyID.encode('utf-8')
arg2 = accountSecret.encode('utf-8')
arg3 = sessionToken.encode('utf-8')
CLibTC.start(2,argv,arg1,arg2,arg3)
print('Everything is fine!!!')
def main():
logging.info("XDG_CACHE_HOME env variable value: {}".format(os.environ.get(HOME)))
logging.info("user in python: {}".format(getpass.getuser()))
sys.path.insert(0,'')
p1 = Process(target=StartVideoStreaming, args=('channeltest666',))
p1.start()
p1.join()
Is there a way to call c lib from python and force it to run as gcc_user? According to me it should have been running as gcc_user at first place because its just a function call from python code.
It should be char username [10], without the *. Maybe there are other problems too but try to fix that first.
Thanks in advance for the help!
I am trying to record calls using the Linphone SDK in Swift on Mac OS, and am having trouble passing a path into the function:
func linphone_call_params_set_record_file(_ cp: OpaquePointer!, _ path: UnsafePointer<Int8>!)
that works correctly (the SDK is written in C, though I am accessing it using Swift and a bridging header). The Linphone SDK works properly, and I can make and receive calls programmatically, with full audio support.
In trying to invoke the call recorder, I pass this function a path (pathtofile), such as:
let pathtofile = "/Users/Alex/Safety/1.wav"
where I would like to store the recording file.
func SafetyNetAVRecorderInitializer(pathtofile: String) -> Bool {
// Convert pathtofile to UnsafePointer<Int8>.
let cpathtofile = (pathtofile as NSString).utf8String
let path = UnsafeMutablePointer<Int8>(mutating: cpathtofile)
// Actually begin call recording.
if currentcall != nil {
let currentcallparameters = linphone_call_get_current_params(currentcall)
linphone_call_params_set_record_file (currentcallparameters, path)
linphone_call_start_recording(currentcall)
return true
}
return false
}
No runtime errors are encountered on linphone_call_params_set_record_file(), but when I try to invoke linphone_call_start_recording(), the recording does not begin, and an error is printed in the console that reads:
ortp-error-linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file().
How can I correctly pass a valid path to linphone_call_params_set_record_file()? I have tried directly passing a plain Swift String instead of an UnsafePointer<Int8> to no avail. Am I just misunderstanding how paths are formatted in C?
For reference, the SDK method source is:
void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){
if (cp->record_file){
ms_free(cp->record_file);
cp->record_file=NULL;
}
if (path) cp->record_file=ms_strdup(path);
}
Thanks again!
Try this:
let cpathtofile = (pathtofile as NSString).utf8String! // Unwraps!
...
inphone_call_params_set_record_file(currentcallparameters, cpathtofile)
from the "Bluetooth Device Access Guide", I've read that the Bluetooth API should be accessable from C or from C++. I've found some C-headers (IOBluetoothUserLib.h, Bluetooth.h) in the IOBluetooth framework that are related to Bluetooth and contain enumerations and data structured to define search creteria but I fail to find any function that takes such enumeration or data structure as parameter. According to the documentation I would have to create a CBCentralManager but I fail to find a way to do so from C or C++.
Background: We use OS/X as a developing plattform for devlopment of BLE enabled microcontrollers. To update firmware on this microcontrollers I want to write a BLE bootloader and I want to have a commandline client to update the firmware. All of the code is written in C++ and I wouldn't like to learn objectiv-C for this small task.
Any pointers, documentation, examples?
thank you
Torsten
According to the documentation I would have to create a CBCentralManager but I fail to find a way to do so from C or C++.
The documentation you refer to is for classic Bluetooth, for which the IOBluetooth framework has some functionality. CBCentralManager is the manager from CoreBluetooth, which is for Bluetooth LE only.
For classic Bluetooth, the manager you want is the HID Manager from the IOKit framework, documentation for which can be found here. If you search around, you'll find lots of examples of C++ usage of IOKit and IOHIDManager (1, 2).
IOKit may in fact give you all the functionality you need, but IOBluetooth supplies some Bluetooth specific features. From Developing Bluetooth Applications:
Although you don’t need to use the Bluetooth API to access a HID-class device, you may choose to use functions or methods from the Bluetooth framework to enhance the user’s experience. For example, your application can provide Bluetooth-specific information that lets the user know if a device doesn’t support a particular service.
I agreed with Henrik you'll need some glue. Look at RedBearLab guys work and precise to class.
ofxBLE. h/mm
// C++ interface //
// (Obj-C may be a superset of C, but this just makes interopability
// easier with oF)
class ofxBLE {
protected:
ofxBLEDelegate *btDelegate;
public:
ofxBLE();
~ofxBLE();
void scanPeripherals();
void sendPosition(uint8_t x, uint8_t y);
bool isConnected();
};
...
- (void)bleDidDisconnect {
NSLog(#"->Disconnected");
}
- (void)bleDidReceiveData:(unsigned char *)data length:(int)length {
}
#end
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
//= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// C++ class implementation
ofxBLE::ofxBLE() {
btDelegate = [[ofxBLEDelegate alloc] init];
}
ofxBLE::~ofxBLE() {
}
void ofxBLE::scanPeripherals(){
[btDelegate scanForPeripherals];
}
void ofxBLE::sendPosition(uint8_t x, uint8_t y) {
// position should be NORMALIZED to between 0 and 255 BEFORE
// passing into this method!
[btDelegate sendPositionX:x withY:y];
}
I tried to call a function from external DLL in Python.
The function prototype is:
void Myfunction(int32_t *ArraySize, uint64_t XmemData[])
This function creates a table of uint64 with "ArraySize" elements. This dll is generated by labview.
Here is the Python code to call this function:
import ctypes
# Load the library
dllhandle = ctypes.CDLL("SharedLib.dll")
#specify the parameter and return types
dllhandle.Myfunction.argtypes = [ctypes.c_int,ctypes.POINTER(ctypes.c_uint64)]
# Next, set the return types...
dllhandle.Myfunction.restype = None
#convert our Python data into C data
Array_Size = ctypes.c_int(10)
Array = (ctypes.c_uint64 * Array_Size.value)()
# Call function
dllhandle.Myfunction(Array_Size,Array)
for index, value in enumerate(Array):
print Array[index]
When executing this I got the error code:
dllhandle.ReadXmemBlock(Array_Size,Array)
WindowsError: exception: access violation reading 0x0000000A
I guess that I don't pass correctly the parameters to the function, but I can't figure it out.
I tried to sort simple data from the labview dll like a uint64, and that works fine; but as soon as I tried to pass arrays of uint64 I'm stuck.
Any help will be appreciated.
It looks like it's trying to access the memory address 0x0000000A (which is 10). This is because you're passing an int instead of a pointer to an int (although that's still an int), and you're making that int = 10.
I'd start with:
import ctypes
# Load the library
dllhandle = ctypes.CDLL("SharedLib.dll")
#specify the parameter and return types
dllhandle.Myfunction.argtypes = [POINTER(ctypes.c_int), # make this a pointer
ctypes.c_uint64 * 10]
# Next, set the return types...
dllhandle.Myfunction.restype = None
#convert our Python data into C data
Array_Size = ctypes.c_int(10)
Array = (ctypes.c_uint64 * Array_Size.value)()
# Call function
dllhandle.Myfunction(byref(Array_Size), Array) # pass pointer using byref
for index, value in enumerate(Array):
print Array[index]
Is there a way to create a Simulink bus from the definition of a C struct? Let's say I have some C struct definition in a header file:
typedef struct {
double a, b;
} u_T;
Can I use this to automatically generate a Simulink.Bus object?
Edit: Is there a tool that generates Matlab code for creating Simulink.Bus objects describing the structs from a .h file?
This is supported in the latest version of MATLAB (2017a). Use the following command.
importInfo = Simulink.importExternalCTypes(headerFiles)
For more info see: https://www.mathworks.com/help/simulink/slref/simulink.importexternalctypes.html
You can import a header when creating a bus object, but this is only used for code generation with Simulink Coder, not for normal simulation with Simulink. See the documentation on Simulink.Bus for more details.
The only way to do what you want would be to write a parser that reads your .h file and creates a bus object in the MATLAB workspace. I don't know of any such tool I'm afraid.
Here is a MATLAB script:
filename = 'Test3.h';
fid = fopen(filename);
tline = fgetl(fid);
i = 1;
while ischar(tline)
% Search for structs
if any(strfind(tline,'typedef struct'))
tline = fgetl(fid);
% Get elements
while ~any(strfind(tline,'}'))
% Create Element
el(i) = Simulink.BusElement;
c = regexp(tline,'(\w*) (\w*);','tokens');
% Element Name
el(i).Name = c{1,1}{1,2};
% Element Data type
switch c{1,1}{1,1}
case 'float'
el(i).DataType = 'single';
case 'int8_t'
el(i).DataType = 'int8';
case 'uint32_t'
el(i).DataType = 'uint32';
% Add unknown Data types as cases here
otherwise
el(i).DataType = ['Bus: ',c{1,1}{1,1}];
end
i = i+1;
tline = fgetl(fid);
end
% Get struct name
c = regexp(tline,'} (\w*);', 'tokens');
% Create bus
eval([c{1,1}{1,1},' = Simulink.Bus;']);
% Assign elements
eval([c{1,1}{1,1},'.Elements = el;']);
% Assign Header file
eval([c{1,1}{1,1},'.HeaderFile = ''',filename,''';']);
clear el; i = 1;
end
tline = fgetl(fid);
end
fid = fclose(fid);
clear c fid filename i tline;
I hope it helps...