2

I need to run a series of python scripts calculating various scripts, that are working fine, but one of them runs very slowly and has to be done in C++. The C++ code is ready, but I need to find a way to call the C++ function from the python and get the return value.

I found information about SWIG, but didn't get it to work on Windows with Visual Studio (I have to do it in VS on Windows, because of other constraints). I found ctypes much easier for my very simple function with standart input and output values.

So I did many tests with ctypes, tried all the examples I could find online, and each and every time, what happens is that I can load the dll (built with visual studio 2012 compiler) but when I try calling the function in python, it just goes :

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    print maLib.plop()
  File "C:\Python27\lib\ctypes\__init__.py", line 378, in __getattr__
    func = self.__getitem__(name)
  File "C:\Python27\lib\ctypes\__init__.py", line 383, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'plop' not found

The python code is (test.py) :

from ctypes import cdll
lib = cdll.LoadLibrary('test')
print lib.plop()

The C++ code is (test.cpp, compiled as test.dll, Visual Studio set to build as dll) :

extern "C"
{
    int plop();
}

int plop() { return 4; }

As you can see, I tried to make it as simple as possible, to avoid details making it fail. I have read the python ctypes help, and tutorials on how to use ctypes, trying exactly the same codes as them, but I had to adapt a bit because I am using Visual Studio / windows and most of the other users are using linux. All of the files are in the same folder.

I have tried multiple ways of loading the library : LoadLibrary('./name.dll'), WinDLL('name.dll'), giving the function a different name, void return type, etc...

Do you think I should use SWIG ? Is my problem an obvious beginner mistake ? I am a student, and new to most of what I'm using, but I put a lot of effort in this, even if I just need it for a particular single task. When using SWIG, I had to make a wrapper with function pointers, or references, so I thought this was the problem, which made me want to try a simpler solution.

I am using : Python 2.7.7, Visual Studio 2012, Windows 8.1

Many thanks in advance

PhilDenfer
  • 270
  • 4
  • 13
  • 1
    See this: http://stackoverflow.com/questions/7586504/python-accessing-dll-using-ctypes –  Jul 04 '14 at 13:29
  • I learned from this link that using WinDLL might be wrong because windows dlls are different. Changed it back, still doesn't work, will update question, then try to understand in the rest of the code what applies to my problem. Thanks, will comment again when stuck again, or hopefully that'll work. – PhilDenfer Jul 04 '14 at 13:46

2 Answers2

11

The error reported by your Python is very clear.

function 'plop' not found

This means that the DLL does not export a function of that name. So, you need to export the function. Either with a .def file, or using __declspec(dllexport):

extern "C"
{
    __declspec(dllexport) int plop();
}

To inspect your DLL to debug issues like this, use dumpbin or Dependency Walker.

Note that since you do not specify calling convention, the default of __cdecl is used. That means that cdll is correct on the ctypes side.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
3

You need to give your function "C" linkage to avoid name mangling. Declare it like this:

extern "C"
{
    int plop();
}

and it will then properly be called "plop" rather than being name-mangled.

RichieHindle
  • 272,464
  • 47
  • 358
  • 399
  • Is it something to put in a header ? Or is the same file ? If so, should I put it before or after the function definition ? I just tried with the definition inside extern C, and also with extern C and the prototype above the definition. It's something that I saw in the SWIG examples, I did it in my SWIG tests but I might be doing it wrong, putting it in the wrong place. – PhilDenfer Jul 04 '14 at 13:29
  • It should go before the function definition; it doesn't matter whether it's in a header or not. – RichieHindle Jul 04 '14 at 13:30
  • I'm sorry, it doesn't work yet, I'm updating the question with the new code. I don't know what's missing (I triple checked that it builded from the new code and deleted the old DLLs, and the error from the python interpreter is exactly the same). – PhilDenfer Jul 04 '14 at 13:35