Reputation: 89
I am writing a program in C using Python API.
Python will pass the input(structure) to C program and C program will perform some operations based on the input.
Could anyone please tell me is it possible to pass structure between Python and C. If yes kindly let me know how to pass it.
I have used SWIG interface to pass values between C and Python. Sample program is working fine (Using variables). I have added code with structure, but i am not sure about the code format for that. Please correct me if i am doing anything wrong. I am completely new to Python and C. I searched everywhere for passing structure using SWIG, i couldn't get any correct answer.
Logic is to fetch the input values from Python and perform the multiplication operation in c and return the values to Python.
Sample.c
#include<stdio.h>
#include "sample.h"
struct info sample;
int getstruct (struct info sample);
int getstruct (struct info sample) {
int i = 0;
int j = 0;
int k = 0;
int l = 0;
i = 2 * sample.i;
j = 2 * sample.j;
k = 2 * sample.k;
l = 2 * sample.l;
sample.i = i;
sample.j = j;
sample.k = k;
sample.l = l;
return(&sample);
}
sample.h
struct info
{
int i;
int j;
int k;
int l;
};
extern struct info data;
sample.i
%module sample
%{
#include "sample.h"
%}
%include "sample.h"
sample.py (automatically generated by SWIG)
# This file was automatically generated by SWIG (http://www.swig.org).
# Version 2.0.11
#
# Do not make changes to this file unless you know what you are doing--modify
# the SWIG interface file instead.
from sys import version_info
if version_info >= (2,6,0):
def swig_import_helper():
from os.path import dirname
import imp
fp = None
try:
fp, pathname, description = imp.find_module('_sample', [dirname(__file__)])
except ImportError:
import _sample
return _sample
if fp is not None:
try:
_mod = imp.load_module('_sample', fp, pathname, description)
finally:
fp.close()
return _mod
_sample = swig_import_helper()
del swig_import_helper
else:
import _sample
del version_info
try:
_swig_property = property
except NameError:
pass # Python < 2.2 doesn't have 'property'.
def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
if (name == "thisown"): return self.this.own(value)
if (name == "this"):
if type(value).__name__ == 'SwigPyObject':
self.__dict__[name] = value
return
method = class_type.__swig_setmethods__.get(name,None)
if method: return method(self,value)
if (not static):
self.__dict__[name] = value
else:
raise AttributeError("You cannot add attributes to %s" % self)
def _swig_setattr(self,class_type,name,value):
return _swig_setattr_nondynamic(self,class_type,name,value,0)
def _swig_getattr(self,class_type,name):
if (name == "thisown"): return self.this.own()
method = class_type.__swig_getmethods__.get(name,None)
if method: return method(self)
raise AttributeError(name)
def _swig_repr(self):
try: strthis = "proxy of " + self.this.__repr__()
except: strthis = ""
return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
try:
_object = object
_newclass = 1
except AttributeError:
class _object : pass
_newclass = 0
class info(_object):
__swig_setmethods__ = {}
__setattr__ = lambda self, name, value: _swig_setattr(self, info, name, value)
__swig_getmethods__ = {}
__getattr__ = lambda self, name: _swig_getattr(self, info, name)
__repr__ = _swig_repr
__swig_setmethods__["i"] = _sample.info_i_set
__swig_getmethods__["i"] = _sample.info_i_get
if _newclass:i = _swig_property(_sample.info_i_get, _sample.info_i_set)
__swig_setmethods__["j"] = _sample.info_j_set
__swig_getmethods__["j"] = _sample.info_j_get
if _newclass:j = _swig_property(_sample.info_j_get, _sample.info_j_set)
__swig_setmethods__["k"] = _sample.info_k_set
__swig_getmethods__["k"] = _sample.info_k_get
if _newclass:k = _swig_property(_sample.info_k_get, _sample.info_k_set)
__swig_setmethods__["l"] = _sample.info_l_set
__swig_getmethods__["l"] = _sample.info_l_get
if _newclass:l = _swig_property(_sample.info_l_get, _sample.info_l_set)
def __init__(self):
this = _sample.new_info()
try: self.this.append(this)
except: self.this = this
__swig_destroy__ = _sample.delete_info
__del__ = lambda self : None;
info_swigregister = _sample.info_swigregister
info_swigregister(info)
# This file is compatible with both classic and new-style classes.
cvar = _sample.cvar
Error message:
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sample
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "sample.py", line 28, in <module>
_sample = swig_import_helper()
File "sample.py", line 24, in swig_import_helper
_mod = imp.load_module('_sample', fp, pathname, description)
ImportError: ./_sample.so: undefined symbol: data
>>>
Commands used:
swig -python sample.i
gcc -fPIC -c sample.c sample_wrap.c -I/usr/include/python2.7
ld -shared sample.o sample_wrap.o -o _sample.so
Upvotes: 0
Views: 1466
Reputation: 1456
You can check out swig.
I use it myself and can confirm that it works quite well. Check out the tutorial for a python example.
The following code is executing:
Header file:
#include<stdio.h>
typedef struct
{
int i;
int j;
int k;
int l;
} MyStruct;
extern MyStruct sample;
extern int getstruct (MyStruct sample);
C file
#include "example.h"
int getstruct (MyStruct sample) {
int i = 0;
int j = 0;
int k = 0;
int l = 0;
i = 2 * sample.i;
j = 2 * sample.j;
k = 2 * sample.k;
l = 2 * sample.l;
sample.i = i;
sample.j = j;
sample.k = k;
sample.l = l;
return(&sample);
}
Interface file:
%module example
%{
#include "example.h"
%}
%include "example.h"
Compile and link files:
$ swig -python example.i
$ gcc -fPIC -c example.c example_wrap.c -I/usr/include/python2.7
$ gcc -lpython -shared example.o example_wrap.o -o _example.so
Now to python:
>>> import example
>>> a = example.MyStruct
>>> dir(a)
['__class__', '__del__', '__delattr__', '__dict__', '__doc__',
'__format__', '__getattr__', '__getattribute__', '__hash__',
'__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__swig_destroy__', '__swig_getmethods__',
'__swig_setmethods__', '__weakref__', 'i', 'j', 'k', 'l', 'this']
>>> a.i = 1
>>> a.j = 1
>>> a.k = 1
>>> a.l = 1
>>> example.getstruct(a)
1605330080
I am not sure what the result is (the address of sample maybe?).
PS:I had a look at the reply from Lee Daniel Crocker, it deserves consideration.
Upvotes: 2