Stugal
Stugal

Reputation: 880

C Method returning string to Python via ctypes

Few years ago I had to create a python wrapper for a C library. My knowledge of C is very limited but I managed to create what was needed. Suddenly one method started causing issues, my only guess is it has to do something with python update.

In any case, I had the following C code:

const char * myFunction()
{
    return "My String";
}

DLL_EXPORT const char*
test()
{
    return myFunction();
}

which in my Python wrapper was called using the following method:

def test(self):
        ret = self.lib.test()

        return c_char_p(ret).value

As stated before, this was working well, although I'm not really sure why given what I've recently discovered while trying to fix it.

Currently that I'm getting 'Seg Fault' from python when calling the method test().

Using this threads:

ctypes return a string from c function

When to use malloc for char pointers

I managed to fix my code which now looks like this, c:

const char * myFunction()
{
    return "My String";
}

DLL_EXPORT const char*
test()
{
    const char* st = myFunction();
    char *bar = _strdup(st);

    return bar;
}

The python code remains the same. As said before, my knowledge of C is very limited and hence few questions:

  1. any idea why the old implementation was working and suddenly stopped? Was there some python update that could have had affected it?
  2. why in my c test() function do I have to do _strdup(st) and return bar instead of simply returning st?

Upvotes: 2

Views: 1641

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 178334

Are you using 64-bit Python? The return type of self.lib.test defaults to c_int which is 32-bit. If pointers are 64-bit you are truncating the pointer. You are probably just getting lucky in your code change that the _strdup is located below 4GB in memory.

If you declare:

self.lib.test.restype = c_char_p

then this should work:

def test(self):
    ret = self.lib.test()
    return ret.value

Upvotes: 2

Related Questions