2

I follow instructions of this page to try to call C++ functions.
Calling C/C++ from Python?

I write a pylib.cpp

#include <iostream>

class Foo {
public:
    void bar() {
        std::cout << "Hello" << std::endl;
    }
};

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

and then use these commands on Win 10 terminal:

g++ -c -fPIC pylib.cpp -o pylib.o
g++ -shared -Wl,-soname,pylib.so -o pylib.so  pylib.o

I get the message in the terminal. Just a warning. The pylib.so still be maked by g++.

pylib.cpp:1:0: warning: -fPIC ignored for target (all code is position independent)
 #include <iostream>
 ^

I write a pylib.py:

from ctypes import *

lib = cdll.LoadLibrary('pylib.so')
f = lib.Foo()
f.bar()

I got the error message:

Traceback (most recent call last):
  File "C:/Users/Jack/PycharmProjects/dip_hw1/pylib.py", line 3, in <module>
    lib = cdll.LoadLibrary('pylib.so')
  File "C:\Python\lib\ctypes\__init__.py", line 426, in LoadLibrary
    return self._dlltype(name)
  File "C:\Python\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 1114] 動態連結程式庫 (DLL) 初始化例行程序失敗。

OSError: [WinError 1114] 動態連結程式庫 (DLL) 初始化例行程序失敗。
this meaning likes
OSError: [WinError 1114] Dynamic-link library (DLL) initialization routine failed

My environment is

Python: Python 3.6.6 (v3.6.6:4cf1f54eb7, Jun 27 2018, 03:37:03) [MSC v.1900 64 bit (AMD64)] on win32
C/C++ Compiler: TDM-GCC MinGW
OS: Win 10

I can load C library well. but I continue get dll error after trying a lot of various methods to write the C++ code, or to make share library with different way.


Note that: the name of cpp library changes to pylib2.dll. whatever I use .so for .dll for dll file name, I get the same error.

This is the command example

C:\Users\Jack\PycharmProjects\dip_hw1>dir
 磁碟區 C 中的磁碟沒有標籤。
 磁碟區序號:  1AB4-8568

 C:\Users\Jack\PycharmProjects\dip_hw1 的目錄

2018/09/20  下午 03:26    <DIR>          .
2018/09/20  下午 03:26    <DIR>          ..
2018/09/20  下午 10:49    <DIR>          .idea
2018/09/18  上午 11:12    <DIR>          image
2015/06/28  下午 02:28            58,880 libatomic-1.dll
2015/06/28  下午 02:28            69,120 libatomic_64-1.dll
2013/09/01  上午 09:38           149,207 libcharset-1.dll
2015/06/28  上午 05:50           145,934 libgcc_s_dw2-1.dll
2015/06/28  下午 02:28           114,176 libgcc_s_seh_64-1.dll
2015/06/28  下午 02:28           120,832 libgcc_s_sjlj-1.dll
2015/06/28  下午 02:28           934,400 libiconv-2.dll
2014/04/27  上午 06:46           484,613 libintl-8.dll
2015/06/28  下午 02:28           359,936 libquadmath-0.dll
2015/06/28  下午 02:28           354,816 libquadmath_64-0.dll
2015/06/28  下午 02:28            13,824 libssp-0.dll
2015/06/28  下午 02:28            18,944 libssp_64-0.dll
2015/06/28  下午 02:28         1,374,208 libstdc++-6.dll
2015/06/28  下午 02:28         1,405,952 libstdc++_64-6.dll
2015/06/28  下午 02:28            11,264 libvtv-0.dll
2015/06/28  下午 02:28            15,872 libvtv_64-0.dll
2015/06/28  下午 02:28            11,264 libvtv_stubs-0.dll
2015/06/28  下午 02:28            15,872 libvtv_stubs_64-0.dll
2015/06/28  下午 02:28            60,928 libwinpthread-1.dll
2015/06/28  下午 02:28            64,512 libwinpthread_64-1.dll
2018/09/17  下午 04:55             1,918 main.cpython-36.pyc
2018/09/19  下午 12:14            10,587 main.py
2018/09/19  下午 08:11           113,157 pylib.dll
2018/09/20  下午 03:26               188 pylib.py
2018/09/19  下午 11:02         2,695,132 pylib2.dll
2018/09/19  下午 11:07         2,695,135 pylib2.so
2018/09/17  下午 04:56                26 run.bat
2018/09/19  下午 02:05               627 test.py
2018/09/17  下午 04:55    <DIR>          __pycache__
              28 個檔案      11,301,324 位元組
               5 個目錄  171,916,886,016 位元組可用

C:\Users\Jack\PycharmProjects\dip_hw1>python pylib.py
C:\Users\Jack\PycharmProjects\dip_hw1
C:\Users\Jack\PycharmProjects\dip_hw1
Traceback (most recent call last):
  File "pylib.py", line 7, in <module>
    lib = cdll.LoadLibrary('pylib2.dll')
  File "C:\Python\lib\ctypes\__init__.py", line 426, in LoadLibrary
    return self._dlltype(name)
  File "C:\Python\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 1114] 動態連結程式庫 (DLL) 初始化例行程序失敗。

And this is the new pylib.py code

from ctypes import *
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
print(dir_path)
print(os.getcwd())

lib = cdll.LoadLibrary('pylib2.dll')
f = lib.Foo()
f.bar()
Roy
  • 43
  • 5
  • 1
    Is this a windows DLL or as Posix shared object you have created? Do you have all the DLLs that pylib.so references available (on the path basically) - check with depends.exe (if you don't know what that is, search for it and download it **now** - it's a vital tool in a Windows developer's armoury). – Martin Bonner supports Monica Sep 19 '18 at 13:46
  • What platform are you on? For Window's Id advise Microsoft Visual Studio Community (free), or at least some tool rather than manual command lines, and you certainly want a DLL, not an so. – Fire Lancer Sep 19 '18 at 13:48
  • If **pylib.so** is a C share library which is build by **gcc** command, then cdll.LoadLibrary('pylib.so') work. So it's seem to not require .dll. – Roy Sep 19 '18 at 13:55
  • I survey a lot of ctypes usages, they all use command line. Not using any certain IDE like Visual Studio. – Roy Sep 19 '18 at 13:58

2 Answers2

2

I find the solution by myself. The solution is:

  1. Using MinGW comipler or Microsoft C/C++ compiler.
  2. Using Python 32 bit interpreter.
  3. It is not necessary to copy dll from compiler bin folder.

First, I used the TDM-GCC MinGW Compiler as C/C++ compiler before. Then I try another compiler: MinGW. I can't tell you what different between them, I'm not a pro guy. But they produce different error message when I use ctypes to load the two different dll library which compile by both in the Python 3.6.6 64 bit interpreter. They all failed on Python 3.6.6 64 bit interpreter.

I try 32-bit python to load dll library. It successes to load library.
The pylib.cpp code:

#include <iostream>
using namespace std;

class Foo {
public:
    void bar() {
        cout << "Hello" << endl;
    }
};

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

Compile command:

g++ -shared -o pylib.dll pylib.cpp

The pylib.py code:

from ctypes import *

lib = cdll.LoadLibrary('pylib.dll')
f = lib.Foo_new()
lib.Foo_bar(f)

The ouput:

Hello

Thanks for pschill and others propose new methods.

Roy
  • 43
  • 5
0

You are using gcc from MinGW to compile and link the code. Since the code uses the C++ standard library (#include <iostream> resp. std::cout), you need to make the libstdc++-6.dll file available which ships with gcc. Copy the .dll into the working directory, then it should work.

pschill
  • 5,055
  • 1
  • 21
  • 42
  • I use g++ to compile. – Roy Sep 19 '18 at 14:31
  • Yes, using g++ is correct. _gcc_ stands for GNU Compiler Collection and the C++ compiler of gcc is g++. – pschill Sep 19 '18 at 14:32
  • I will get error when I use gcc to compile the .cpp code. – Roy Sep 19 '18 at 14:32
  • Oh! So I need to find and copy libstdc++-6.dll into the directory that the .so file locate? I think it is the working directory you talk about. – Roy Sep 19 '18 at 14:34
  • You need to copy `libstdc++-6.dll` into the *working directory*. Since you are using `cdll.LoadLibrary('pylib.so')` to load the library, the working directory also seems to be the directory that contains the .so file. The .dll is probably located in a bin/ directory somewhere near g++.exe. – pschill Sep 19 '18 at 14:38
  • I copy all the .dll in the `TDM-GCC-64\bin` to the working directory. But I get the same dll error again... – Roy Sep 19 '18 at 15:07
  • I use `os.path.dirname(os.path.realpath(__file__))` to locate working directory. I find the dir is `C:\Users\Jack\PycharmProjects\dip_hw1`. I put all the .dll into `dip_hw1`. – Roy Sep 19 '18 at 15:10
  • The working directory can be seen with `os.getcwd()`. What does this function return for you? – pschill Sep 20 '18 at 04:56
  • The same `C:\Users\Jack\PycharmProjects\dip_hw1` – Roy Sep 20 '18 at 07:27
  • Strange that it didnt work. I could reproduce the exact same error (except for the chinese translation) and copying the dll fixed it for me. – pschill Sep 20 '18 at 09:46
  • I write the command example up to main question. You could check that for whether I do some mistakes. – Roy Sep 20 '18 at 15:00