当一个函数(来自共享库)由独立的可执行文件执行时,以及使用Python的ctypes调用完全相同的函数时,我得到的是同一个共享库的不同结果。 差异缩小为库使用的libm版本。 当使用独立可执行文件中的库时,我们链接openlibm,但是当库通过ctypes链接时,它与Ubuntu的libm链接。如何使ctypes链接我的共享库与openlibm?
共享库头(fft.h):
extern "C" {
void fft(const char* srcPath);
};
共享库实现(fft.cpp):
#include <iostream>
#include <fstream>
#include <nlohmann/json.hpp>
#include <Eigen/Eigen>
#include <unsupported/Eigen/FFT>
void fft(const char* srcPath) {
std::cout.precision(17);
std::ifstream fs(srcPath, std::ofstream::in);
// Get length of file
fs.seekg(0, std::ifstream::end);
auto length = fs.tellg();
fs.seekg(0, std::ifstream::beg);
// Read the file
auto srcRaw = new char[length];
fs.read(srcRaw, length);
// Convert data to vector of doubles
nlohmann::json j = nlohmann::json::parse(srcRaw);
std::vector<double> srcDoubles = j;
int n = 65536;
Eigen::VectorXd srcEigen(n);
Eigen::VectorXcd dstEigen(n);
std::copy(srcDoubles.data(), srcDoubles.data() + srcDoubles.size(), srcEigen.data());
Eigen::FFT<double> fft;
fft.fwd(dstEigen, srcEigen);
std::vector<std::complex<double>> dstTmp(dstEigen.data(), dstEigen.data() + dstEigen.size());
for (size_t i = 0; i < dstTmp.size(); i++) {
std::cout << "Result[" << i << "] = " << dstTmp[i].real() << "+i*" << dstTmp[i].imag() << std::endl;
}
delete[] srcRaw;
}
使用独立可执行文件中的库:
#include <fft.h>
int main(int argc, char** argv) {
fft("input_data");
}
使用Python的ctypes:
from ctypes import c_char_p, CDLL
class LibCFft(CDLL):
def __init__(self):
super(LibCFft, self).__init__("libexample.so")
self._addfunc('fft', [c_char_p], None)
def _addfunc(self, name, argtypes, restype):
attr = getattr(self, name)
attr.argtypes = argtypes
attr.restype = restype
return lambda x: x
class CFft(object):
def fft(self):
LibCFft().fft("input_data")
if __name__ == '__main__':
CFft().fft()
Lib构建:
clang++ /opt/eigen-eigen-43d9075b23ef -isystem /opt/spdlog/include -isystem /opt/nlohmann/include -O3 -DNDEBUG -fPIC -std=gnu++14 -o CMakeFiles/example.dir/fft.cpp.o -c /home/user/fft.cpp
clang++ -fPIC -O3 -DNDEBUG -shared -Wl,-soname,libexample.so -o libbugatone.so CMakeFiles/example.dir/generated/fft.cpp.o -lopenlibm
可执行的构建:
clang++ -O3 -DNDEBUG -latomic -nodefaultlibs -lopenlibm -lc -lc++ -lgcc -lgcc_s -lstdc++ -latomic -lm CMakeFiles/eigen_tester.dir/eigen_tester.cpp.o -o eigen_tester libexample.so -lopenlibm
在此先感谢您的帮助。
在可执行链接步骤中,您使用BOTH -lm和-lopenlibm,这可能不是您想要的。
-nodefaultlibs禁用自动包含所有标准库,所以如果你不包含-lm但保留-lopenlibm,这应该可以做你想要的。
您可以在您的环境中更新LD_LIBRARY_PATH,首先指向您的本地库文件夹,并在那里保留您的libopenlibm.so并创建一个软链接:'ln -s libopenlibm.so libm.so'。在大多数情况下,会导致任何共享对象将其用作常规libm.so的替换