【问题标题】:Strange Issue Loading DLL into Python with Ctypes in Cygwin在 Cygwin 中使用 Ctypes 将 DLL 加载到 Python 中的奇怪问题
【发布时间】:2017-01-27 23:39:15
【问题描述】:

我已经在这里呆了好几个小时了。我在 Cygwin 和 Clion 上使用 gcc 编译了一个简单的 hello-world .dll。

我有一个 Python 脚本从位于 Cygwin 目录的 Pycharm 中的 anaconda 安装(即解释器)运行。

.dll 文件名为“cygextension_test_c.dll”。


我将 .dll 移动到 python 项目目录,并在下面列出的各种配置中运行以下代码(所有这些都是我今天下午可以找到的关于这个主题的过去十年中提出的各种问题的各种解决方案——我正在使用以下 website 将 ndarrays 发送到 C 代码):

import numpy as N
from numpy.ctypeslib import load_library
from numpyctypes import c_ndarray
import ctypes
import os

print(ctypes.windll.kernel32);

mydll = load_library('cygextension_test_c.dll',r'C:\cygwin64\home\...\extension_test_c\cmake-build-debug');

mydll = ctypes.WinDLL(r'same path, essentially--this time pointing to working directory\cygextension_test_c.dll')

mydll = ctypes.CDLL(r'ditto')

mydll = ctypes.cdll.LoadLibrary('...')

mydll = ctypes.windl.LoadLibrary('...')

myarray = N.zeros((3,13),dtype=N.double)
c_myarray = c_ndarray(myarray,dtype=N.double,ndim=2)

我还单步执行了代码,并注意到路径和文件正在被访问。如果我将路径更改为不正确的内容(或文件名等),我会在链的早期收到不同的错误。这在某种程度上与 .dll 本身有关。但是,几乎所有问题都得到(显然)我得到的相同错误,并且在他们的情况下与实际的 .dll 无关。他们只是通过切换使用 ctypes 导入 .dll 的方式来获得神奇的解决方案。


因此,我再次在(显然)Windows 计算机上的 Cygwin 目录中的 pycharm 上使用 Windows anaconda 安装(python 3.5)。 c++ 代码是在 Clion 中使用 gcc 编译的,在 CMakeLists 文件中具有以下设置(根据上面链接中的说明):

cmake_minimum_required(VERSION 3.6)
project(extension_test_c)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -ansi -pedantic -Wall -pedantic -std=c++0x")

set(SOURCE_FILES extension_test_c.cpp extension_test_c.h ndarray.h)
add_library(extension_test_c SHARED ${SOURCE_FILES})

我在extension_test_c.cpp 中编译的代码只是一个函数,它打印出步幅数组在二维 numpy ndarray 中具有哪些数字(这与链接中的代码有关),并且标题中的代码是更简单;但是,我已经注释掉了std 行,因为我遇到了关于库是否访问其他库的早期问题之一的另一个答案(因为这可能导致 ctypes 导入失败)。

extension_test_c.cpp

#include "extension_test_c.h"

//#include <iostream>
#include "ndarray.h"

extern "C" {
int hello(numpyArray<double> array) {
    Ndarray<double,2> a(array);

    //std::cout << "shape 0: " << array.shape[0] << "; shape 1: " <<
    //          array.shape[1] << "; stride 0: " << array.strides[0]
    //          << "; strides 1: " << array.strides[1] << std::endl;
    return 1; 
}
}

还有头文件:

#ifndef EXTENSION_TEST_C_LIBRARY_H
#define EXTENSION_TEST_C_LIBRARY_H

#include "ndarray.h"
extern "C" {
int hello(numpyArray<double> array); 
}
#endif

ndarray.h 可以在上面网站的链接中找到。


我不知道我做错了什么;我完全没有想法。这是load_library 的错误:

  Traceback (most recent call last):
  File "C:/cygwin64/home/chris/CygwinMachineLearning/Assignment 1/DecisionTree/extension_test_python/wrapper.py", line 9, in <module>
      mydll = load_library('cygextension_test_c.dll',r'C:\cygwin64\home\chris\CygwinMachineLearning\Assignment 1\DecisionTree\extension_test_c\cmake-build-debug');
  File "C:\Anaconda3\envs\tensorflow\lib\site-packages\numpy\ctypeslib.py", line 150, in load_library
      return ctypes.cdll[libpath]
  File "C:\Anaconda3\envs\tensorflow\lib\ctypes\__init__.py", line 422, in __getitem__
      return getattr(self, name)
  File "C:\Anaconda3\envs\tensorflow\lib\ctypes\__init__.py", line 417, in __getattr__
      dll = self._dlltype(name)
  File "C:\Anaconda3\envs\tensorflow\lib\ctypes\__init__.py", line 347, in __init__
      self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found

ctypes.CDLL(...) 的错误:

Traceback (most recent call last):
  File "C:\Program Files (x86)\JetBrains\PyCharm 2016.3.2\helpers\pydev\pydevd.py", line 1596, in <module>
    globals = debugger.run(setup['file'], None, None, is_module)
  File "C:\Program Files (x86)\JetBrains\PyCharm 2016.3.2\helpers\pydev\pydevd.py", line 974, in run 
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "C:\Program Files (x86)\JetBrains\PyCharm 2016.3.2\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "C:/cygwin64/home/chris/CygwinMachineLearning/Assignment 1/DecisionTree/extension_test_python/wrapper.py", line 9, in <module>
    mydll = ctypes.CDLL('cygextension_test_c.dll',r'C:\cygwin64\home\chris\CygwinMachineLearning\Assignment 1\DecisionTree\extension_test_c\cmake-build-debug');
  File "C:\Anaconda3\envs\tensorflow\lib\ctypes\__init__.py", line 347, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found

对于WinDLL,也是一样的。


对于cdll.LoadLibrary 版本,它几乎是相同的(完全相同的最终错误)不同的跟踪:

Traceback (most recent call last):
  File "C:\Program Files (x86)\JetBrains\PyCharm 2016.3.2\helpers\pydev\pydevd.py", line 1596, in <module>
    globals = debugger.run(setup['file'], None, None, is_module)
  File "C:\Program Files (x86)\JetBrains\PyCharm 2016.3.2\helpers\pydev\pydevd.py", line 974, in run
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "C:\Program Files (x86)\JetBrains\PyCharm 2016.3.2\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "C:/cygwin64/home/chris/CygwinMachineLearning/Assignment 1/DecisionTree/extension_test_python/wrapper.py", line 9, in <module>
    mydll = ctypes.cdll.LoadLibrary(r'C:\cygwin64\home\chris\CygwinMachineLearning\Assignment 1\DecisionTree\extension_test_c\cmake-build-debug');
  File "C:\Anaconda3\envs\tensorflow\lib\ctypes\__init__.py", line 425, in LoadLibrary
    return self._dlltype(name)
  File "C:\Anaconda3\envs\tensorflow\lib\ctypes\__init__.py", line 347, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found

【问题讨论】:

  • 您遇到的错误是什么?
  • @griffin2000 啊对,我的 b 一秒

标签: python ctypes


【解决方案1】:

经过数小时为我尝试的解决方案是在 gcc 链接器命令中添加“-static”。来自Gcc Link Options

-静态

在支持动态链接的系统上,这会覆盖 -pie 和 阻止与共享库的链接。在其他系统上,这 选项无效。

[WinError 126] 提示找不到一些依赖的 dll。提示是在不同的 Windows 系统上加载相同的 dll 时。安装 WSL 可能也可以工作,但静态链接为没有 WSL 的机器修复了它。

【讨论】:

    【解决方案2】:

    对于 ctypes.CDLL,库应该没有 .dll 扩展名。

    所以

    myDLL =  ctypes.CDLL("myPath/MyDLL")
    

    不是

    myDLL =  ctypes.CDLL("myPath/MyDLL.dll")
    

    【讨论】:

    • 是的......这似乎也没有任何工作。可能是因为我在 Cygwin 中设置了 C++,而不是纯 Linux/mac/windows 系统?还是我正在做的其他事情?
    • 我有一种模糊的感觉,它也可能与 Windows 上的绝对路径有问题,但不确定。
    • 无论如何,我无法在 cygwin 中引用 Kernel32,我必须添加“.dll”才能使其正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    相关资源
    最近更新 更多