numpy ctype 如果不是每次都重新编译,"dynamic module does not define init function"错误

numpy ctypes "dynamic module does not define init function" error if not recompiled each time

本文关键字:module dynamic does not 错误 function init define 编译 如果不 ctype      更新时间:2023-10-16

对于dynamic module does not define init function的另一个问题感到抱歉。我确实浏览了以前的问题,但我没有找到一个足够具体地针对我的情况。

我有一个c++库,应该导出几个函数到python(像~5函数定义在extern "C" {}块)。当我每次导入库时重新编译它时,它工作得很好。但是,如果我导入它而不重新编译,它会给出错误ImportError: dynamic module does not define init function (initmylib)

复制相同行为(错误)的非常简化的示例如下:

文件mylib.cpp中的c++库代码

#include <math.h>
// there are some internal C++ functions and classes 
// which are not exported, but used in exported functions
extern "C"{
// one of the functions which should be accessible from python
void oscilator( double dt, int n, double * abuff, double * bbuff ){
    double a = abuff[0];
    double b = bbuff[0];
    for (int i=1; i<n; i++){
        a = a - b*dt;
        b = b + a*dt;
        abuff[i] = a;
        bbuff[i] = b;
    }
}
// there are also other functions but let's keep this example simple
// int initmylib( ){ return 0; } // some junk ... if this makes ctypes happy ?
}

python warper mylib.py of c++ library mylib.cpp:

import numpy as np
from   ctypes import c_int, c_double
import ctypes
import os
name='mylib'
ext='.so'  # if compited on linux .so on windows .dll
def recompile( 
        LFLAGS="",
        #FFLAGS="-Og -g -Wall"
        FFLAGS="-std=c++11 -O3 -ffast-math -ftree-vectorize"
    ):
    import os
    print " ===== COMPILATION OF : "+name+".cpp"
    print  os.getcwd()
    os.system("g++ "+FFLAGS+" -c -fPIC "+name+".cpp -o "+name+".o"+LFLAGS)
    os.system("g++ "+FFLAGS+" -shared -Wl,-soname,"+name+ext+" -o "+name+ext+" "+name+".o"+LFLAGS)
# this will recompile the library if somebody delete it
if not os.path.exists("./"+name+ext ):
    recompile()
lib    = ctypes.CDLL("./"+name+ext )
array1d = np.ctypeslib.ndpointer(dtype=np.double, ndim=1, flags='CONTIGUOUS')
# void oscilator( double dt, int n, double * abuff, double * bbuff )
lib.oscilator.argtypes = [ c_double, c_int, array1d, array1d ]
lib.oscilator.restype  = None
def oscilator( dt, a, b ):
    n  = len(a)
    lib.oscilator( dt, n, a, b )
python程序test.py导入mylib
import os
from pylab import *
from basUtils import * 
# this will delete all compiled files of the library to force recompilation
def makeclean( ):
    [ os.remove(f) for f in os.listdir(".") if f.endswith(".so") ]
    [ os.remove(f) for f in os.listdir(".") if f.endswith(".o") ]
    [ os.remove(f) for f in os.listdir(".") if f.endswith(".pyc") ]
# if I do makeclean() every time it works, if I do not it does not
#makeclean( )
import mylib
a=zeros(100)
b=zeros(100)
a[0] = 1
mylib.oscilator( 0.1, a, b )
plot( a )
plot( b )
show()

我还试图通过在mylib.cpp中添加一些int initmylib( ){ return 0; }函数来使ctypes高兴,正如您在上面的代码中看到的那样。但是这会产生错误SystemError: dynamic module not initialized properly

当我从scipy课堂笔记中编译cos_doubles示例时,我没有遇到这个问题。然而,这个例子只适用于我只想导入一个与库名同名的函数。我想要一些更一般的东西。

尝试运行import imp; print imp.find_module('mylib')[1]。你很惊讶它选了我吗?所以不是mylib。py?解释器需要mylib。所以作为一个扩展模块,这对于CPython 2。x应该定义一个名为initmylib的初始化函数。为了避免意外地尝试导入共享库,请将名称更改为_mylib之类的内容。或者mylib。1.0。so——或者直接将文件保存在sys.path以外的目录中。

请注意,Windows扩展模块是dll,但扩展名是.pyd而不是.dll。所以import mylib不会尝试加载mylib.dll。

相关文章: