2

I am trying to interact with a dll from python using ctypes, reading the documentation the C++ method signature is of the following:

my_c_pp_function(user *param1[],const int_8 param2,const int_8 values3[],const int_8 length_param1)

Essentially the c++ function requires a list of users, an integer,a list of values and the number of users, also an integer

Note: the users is a structure containing name,age, and id. Something like:

typedef struct
{
char name[255];
int_16 age;
int_32 uid;
}user;

When I try calling this function from python code using ctypes I do:

def call_my_c_pp_function(list_of_users,int_param2,list_of_values,int_lenght_of_list):


        myparam1=(ctypes.c_char_p * len(list_of_users))(*list_of_users)
        myparam2=ctypes.c_int8(int_param2)
        myparam3=(ctypes.c_int8 * len(list_of_values))(*list_of_values)
        myparam4=ctypes.c_int8(int_lenght_of_list)

    self.dll_object.my_c_pp_function.argtypes(ctypes.POINTER(ctypes.c_char_p),ctypes.c_int8,ctypes.POINTER(ctypes.c_int8),ctypes.c_int8)

        ret_value=self.dll_object.my_c_pp_function(myparam1,myparam2,myparam3,myparam4)

Now every time I call the python function I get an error basically if the function succeeds the return value should be 0, any non zero number indicates some kind of problem.

I keep getting a large non-zero number as the return value. What could I possibly be doing wrong? is the way I'm creating the array of users, and the array of values wrong?

I am not sure how to populate/make use of the c++ user structure in my python code so that my list is not just a list of strings but a list of users

I'm using Python2.7 on Windows

Regards

3
  • If that first parameter is really a std::string * you will have to find some way to populate it, as char * is not a std::string Commented Apr 3, 2016 at 20:58
  • you cannot use std::string in the public interface of the function (since it is a c++ type). ctypes only provides support for C compatible data types. Commented Apr 3, 2016 at 21:11
  • To call it you must know how to construct or otherwise obtain users, but you've not shown us anything about that type. Commented Apr 3, 2016 at 22:00

1 Answer 1

1
+50

Assuming that you cannot change the signature of your library function.

I would recommend you to create a simple adapter for your c++ function, which just acts as an interface to your actual function. This function would just take all the values you need and then convert them to your needed types.

Here is a working example (tested with python27). Note that I added an additional parameter for the number of elements in the int array.

py_caller.py

import ctypes
import os


class user(ctypes.Structure):
    _fields_ = [("name", ctypes.c_char_p),
                ("age", ctypes.c_int),
                ("uid", ctypes.c_int)]


def create_users(count):
    users = (user * count)()
    for i in range(count):
        users[i].name = ctypes.c_char_p("user" + str(i))
        users[i].age = i
        users[i].uid = i * i
    return users


def create_values(count):
    values = (ctypes.c_int * count)()
    for i in range(count):
        values[i] = i ** 2
    return values


def main():
    os.environ['PATH'] += ";" + os.path.dirname(os.path.abspath(__file__))
    dll = ctypes.cdll.LoadLibrary('cppdll')

    count = 4
    users = create_users(count)
    n_users = ctypes.c_int(count)

    values = create_values(count)
    n_values = ctypes.c_int(count)

    some_int = ctypes.c_int(42)

    res = dll.func(users, n_users, some_int, values, n_values)
    print (res)


if __name__ == "__main__":
    main()

export.h

#pragma once

typedef struct t_user
{
  char *name;
  int age;
  int uid;
};

extern "C" __declspec(dllexport) int func(t_user *users, int n_users, int val, int *values, int n_values);

export.cpp

#include "export.h"
#include <iostream>

int func(t_user *users, int n_users, int val, int *values, int n_values)
{
  std::cout << "users:\n";
  for (auto i = 0; i < n_users; ++i)
  {
    std::cout << users[i].name
      << ": " << users[i].age 
      << " - " << users[i].uid << "\n";
  } 

  std::cout << "values:\n";
  for (auto i = 0; i < n_values; ++i)
    std::cout << values[i] << "\n";

  std::cout << "some int: " << val << "\n";

  // do something else with the values
  // such as calling your actual library function

  return 1;
} 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for helping. I really appreciate it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.