user3395194
user3395194

Reputation: 89

Is there a way to pass structure between Python and C

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

Answers (1)

Sigve Karolius
Sigve Karolius

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

Related Questions