1

I am attempting to pass a string from python to a c++ library. However, I have been crashing with variations of segfaults std::bad_alloc, and invalid type messages while I have been attempting to do so. Here is the code that I am attempting to use in c++:

#define DLLEXPORT extern "C"
DLLEXPORT std::string returnAString()
{
  std::string ret = "Returning string from lib";
  return ret;
}

DLLEXPORT char* returnACharArray()
{
  return "Returning char* from lib";
}

DLLEXPORT void passInAString(std::string incomingString)
{
  printf("Recieved message in passInAString\n");
  printf("Recieved incoming message: %s", incomingString);
}

DLLEXPORT void passInACharArray(char* incomingString)
{
  printf("Recieved message in passInACharArray\n");
  printf("Recieved incoming message: %s", incomingString);
}

Realistically, with what I am doing I can work with either the char* or the std::string once it gets in my c++ code, and I don't really have a preference either way. Here is what I am doing in python:

from ctypes import *
import os
libPath = os.path.join(os.getcwd(), "mylib.so")
lib = cdll.LoadLibrary(libPath)

string = "hello from python"
lib.passInAString(string)
#lib.passInACharArray(string)
#ret = lib.returnAString()
#print("recieved string: " + string)
#ret = lib.returnACharArray()
#print("recieved char*: " + string)

here, I will uncomment whichever line I am attempting to test. When passing in a string, I will get my first printf statement, I will get std::bad_alloc. When I pass in a char*, I get a segfault. When I attempt to receive a message, I get back a number (I am assuming that this is the pointer), but I am unable to decode this message into an actual string message.

I have attempted to use c_char_p to convert my python string into a char* to pass to my library, but when I do that I get "invalid type". Trying to convert the returned message by doing c_char_p(lib.returnACharArray) and then print(str(string.value)) then gives me the hex value of 4 bytes... which is not what I am returning.

What am I missing to make this functionality work?

1 Answer 1

1

Your DLL has the wrong argument types. Since you're passing a string from Python the function should take a char*. You can convert this to a std::string within the function if you want to.

There's a table in the Python docs showing the corresponding types in both C and Python here: https://docs.python.org/3.6/library/ctypes.html#fundamental-data-types

Edit: Just realized the string types differ for Python 3 meaning the function needs to be declared differently. e.g.

// Python2, or Python3 passing bytes
DLLEXPORT void passInAString(char* incomingString)
{
    printf("Received message in passInAString\n");
    printf("Received incoming message: %s", incomingString);

    std::string myStr = incomingString;
    // and do stuff with myStr if needed
    printf("Incoming message as std::string is %s", myStr.c_str());
}

// Python3 passing strings
DLLEXPORT void passStringPy3(wchar_t* wideString)
{
    printf("Message >>%ls<<\n", wideString);
}
Sign up to request clarification or add additional context in comments.

3 Comments

As you can see from the functions that I have available, I have the function passInACharArray(char* incomingString), which I have tested with. When I use that function though, the code prints out "Recieved message in passInACharArray", followed immediately after by a segfault. Since you say this is the proper method of doing this, how would you write the python that calls this function?
If you're using Python3 I think you need to convert the string to a bytestring. e.g. lib.passInACharArray(thestring.encode('utf-8'))
I've edited the code for proper strings passed from Py3.

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.