Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Submit 'int' and 'string' arrays using ctypes (Python->C++)

Tags:

python

ctypes

I've a simple working program that submits an int (num_piezasin the example) from a Python function to a C++ function.

foo.cpp

#include <iostream>

class Foo{
    public:
        void bar(int number){
            printf("Number is: %d\n", number);
        }
};

extern "C" {
    Foo* Foo_new(){ return new Foo(); }
    void Foo_bar(Foo* foo, int number){ foo->bar(number); }
}

fooWrapper.py

from ctypes import cdll
lib = cdll.LoadLibrary('./libfoo.so')

class Foo(object):
    def __init__(self):
        self.obj = lib.Foo_new()

    def bar(self, num_piezas):
        lib.Foo_bar(self.obj, num_piezas)

num_piezas = 5    
f = Foo()
f.bar(num_piezas)

The thing is that now I want to send an int array and a char array along with that number. So I tried:

foo.cpp

#include <iostream>
#include <string.h>

class Foo{
    public:
        void bar(int number, int piezas[3], char prioridades[3][20]){
            printf("Number is: %d\n", number);
            for(int i=0;i<3;i++) {
                printf("%d", piezas[i]);
            }
            for(int q=0;q<3;q++) {
                printf("%s ", prioridades[q]);
            }
        }
};

extern "C" {
    Foo* Foo_new(){ return new Foo(); }
    void Foo_bar(Foo* foo, int number, int piezas[3], char prioridades[3][20]){ foo->bar(number, piezas, prioridades); }
}

fooWrapper.py

from ctypes import cdll
lib = cdll.LoadLibrary('./libfoo.so')

class Foo(object):
    def __init__(self):
        self.obj = lib.Foo_new()

    def bar(self, num_piezas, piezas, prioridades):
        lib.Foo_bar(self.obj, num_piezas, piezas, prioridades)

piezas = [1, 2, 3]
prioridades = ['normal', 'baja', 'primera pieza']
num_piezas = 5    
f = Foo()
f.bar(num_piezas, piezas, prioridades)

The C++ file compiles correctly, but when I try to execute the Python function (python fooWrapper.py) this error message shows up:

Traceback (most recent call last):
  File "fooWrapper.py", line 15, in <module>
    f.bar(num_piezas, piezas, prioridades)
  File "fooWrapper.py", line 9, in bar
    lib.Foo_bar(self.obj, num_piezas, piezas, prioridades)
ctypes.ArgumentError: argument 3: <type 'exceptions.TypeError'>: Don't know how to convert parameter 3

What I'm doing wrong? Do I need to do something else to pass that int and string arrays as parameters? Thanks in advance.

like image 410
Avión Avatar asked Mar 22 '23 21:03

Avión


1 Answers

You can get away with this modification :

from ctypes import c_int, c_char

...

# create a 3-int array
piezas = (c_int*3)()
piezas[0] = 1
piezas[1] = 2
piezas[2] = 3

# create a 3-(20-char array) array
prio = ((c_char*20)*3)()
prio[0].value = "normal"
prio[1].value = "baja"
prio[2].value = "primera pieza"

But since you're dealing with char arrays in the C++ side part, I would advise you to change your function defintion for : void Bar( int num, char* piezas, int len_piezas, char** prio , int len_prio_elem, int prio);. It is much longer, but you have to control the length of the input arrays if you want to avoid buffer overflows.

like image 143
lucasg Avatar answered Apr 02 '23 23:04

lucasg