在 Cython 中使用 "extern __declspec(dllimport)"
Use "extern __declspec(dllimport)" in Cython
我可以在 Cython 中使用 extern __declspec(dllimport)
吗?我正在尝试将 embree
包装在 Windows 中,但我不确定我是否可以在 Cython 中动态地 link。
我阅读了 this SO post,它非常适合直接更改 C/C++ 和 header 文件,但我不确定如何在 .pxd
中实现它文件。
例如,Embree 2.17.7 x64 header rtcore.h
将 RTCORE_API
定义为
#ifndef RTCORE_API
#if defined(_WIN32) && !defined(EMBREE_STATIC_LIB)
# define RTCORE_API extern "C" __declspec(dllimport)
#else
# define RTCORE_API extern "C"
#endif
#endif
但是,这些在 pyembree pxd file rtcore.pxd
. This seems consistent with the Cython docs 中使用它们的函数签名被遗漏了,
Leave out any platform-specific extensions to C declarations such as __declspec()
但是,即使我通过更改行
将 pyembree setup.py
文件指向我下载的 embree DLL
ext.libraries = ["embree"]
至
ext.libraries = [""C:/Program Files/Intel/Embree v2.17.7 x64/bin/embree""]
我仍然遇到 3 个 linking 错误:
mesh_construction.obj : error LNK2001: unresolved external symbol __imp_rtcMapBuffer
mesh_construction.obj : error LNK2001: unresolved external symbol __imp_rtcNewTriangleMesh
mesh_construction.obj : error LNK2001: unresolved external symbol __imp_rtcUnmapBuffer
build\lib.win-amd64-3.8\pyembree\mesh_construction.cp38-win_amd64.pyd : fatal error LNK1120: 3 unresolved externals
我从 and the Microsoft docs 得知 __imp_
相关的 linker 错误是由于未找到 DLL。但是在rtcore_geometry.h
中可以看到是这样定义的:
在rtcore_geometry.pxd
中定义为:
唯一的区别是 .pxd
文件的签名中不包含 RTCORE_API
。
有谁知道我如何解决这个问题以便 pyembree
能够构建?
EDIT: 还需要注意的是,我已经添加了
# distutils: language=c++
我所有的 .pyx
和 .pxd
文件。 也审核了,但是没有解决我的问题
更新: 将 embree.lib
文件添加到我的本地 pyembree/embree2
文件夹并将 setup.py
更新为
ext.libraries = ["pyembree/embree2/*"]
允许代码通过
编译
py setup.py build_ext -i
但是,这些包没有加载:
>>> import pyembree
>>> from pyembree import rtcore_scene
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: DLL load failed while importing rtcore_scene: The specified module could not be found.
我需要在 setup.py
中定义“子包”吗?这是我现在的 setup.py
:
from setuptools import find_packages, setup
import numpy as np
from Cython.Build import cythonize
from Cython.Distutils import build_ext
include_path = [np.get_include()]
ext_modules = cythonize(
'pyembree/*.pyx',
language_level=3,
include_path=include_path)
for ext in ext_modules:
ext.include_dirs = include_path
ext.libraries = [
"pyembree/embree2/*",
]
setup(
name="pyembree",
version='0.1.6',
cmdclass = {"build_ext": build_ext},
ext_modules=ext_modules,
zip_safe=False,
packages=find_packages(),
include_package_data = True
)
并且目录结构如下(pyembree
是我项目的.venv\lib\site-packages
文件夹中的top-level文件夹):
pyembree
│ .authors.yml
│ .gitignore
│ .mailmap
│ AUTHORS
│ CHANGELOG.rst
│ LICENSE
│ MANIFEST.in
│ pyproject.toml
│ README.rst
│ setup.py
│
├───build
│ └───temp.win-amd64-3.8
│ └───Release
│ └───pyembree
│ mesh_construction.cp38-win_amd64.exp
│ mesh_construction.cp38-win_amd64.lib
│ mesh_construction.obj
│ rtcore.cp38-win_amd64.exp
│ rtcore.cp38-win_amd64.lib
│ rtcore.obj
│ rtcore_scene.cp38-win_amd64.exp
│ rtcore_scene.cp38-win_amd64.lib
│ rtcore_scene.obj
│ triangles.cp38-win_amd64.exp
│ triangles.cp38-win_amd64.lib
│ triangles.obj
│
├───pyembree
│ │ mesh_construction.cp38-win_amd64.pyd
│ │ mesh_construction.cpp
│ │ mesh_construction.h
│ │ mesh_construction.pyx
│ │ rtcore.cp38-win_amd64.pyd
│ │ rtcore.cpp
│ │ rtcore.pxd
│ │ rtcore.pyx
│ │ rtcore_geometry.pxd
│ │ rtcore_geometry_user.pxd
│ │ rtcore_ray.pxd
│ │ rtcore_scene.cp38-win_amd64.pyd
│ │ rtcore_scene.cpp
│ │ rtcore_scene.pxd
│ │ rtcore_scene.pyx
│ │ triangles.cp38-win_amd64.pyd
│ │ triangles.cpp
│ │ triangles.pyx
│ │ __init__.pxd
│ │ __init__.py
│ │
│ ├───embree2
│ │ embree.lib
│ │ rtcore.h
│ │ rtcore.isph
│ │ rtcore_builder.h
│ │ rtcore_geometry.h
│ │ rtcore_geometry.isph
│ │ rtcore_geometry_user.h
│ │ rtcore_geometry_user.isph
│ │ rtcore_ray.h
│ │ rtcore_ray.isph
│ │ rtcore_scene.h
│ │ rtcore_scene.isph
│ │ rtcore_version.h
│ │ tbb.lib
│ │ tbbmalloc.lib
│ │
│ └───__pycache__
│ __init__.cpython-38.pyc
│
└───tests
test_intersection.py
一旦我手动将 DLL
复制并粘贴到我的 .venv\Lib\site-packages
文件夹中生成的 .egg
文件夹中,代码就会正常运行:
pyembree-0.1.6-py3.8-win-amd64.egg
├───EGG-INFO
│ dependency_links.txt
│ native_libs.txt
│ not-zip-safe
│ PKG-INFO
│ SOURCES.txt
│ top_level.txt
│
└───pyembree
│ embree.dll
│ freeglut.dll
│ mesh_construction.cp38-win_amd64.pyd
│ mesh_construction.cpp
│ mesh_construction.py
│ rtcore.cp38-win_amd64.pyd
│ rtcore.cpp
│ rtcore.py
│ rtcore_scene.cp38-win_amd64.pyd
│ rtcore_scene.cpp
│ rtcore_scene.py
│ tbb.dll
│ tbbmalloc.dll
│ triangles.cp38-win_amd64.pyd
│ triangles.cpp
│ triangles.py
│ __init__.py
│
└───__pycache__
mesh_construction.cpython-38.pyc
rtcore.cpython-38.pyc
rtcore_scene.cpython-38.pyc
triangles.cpython-38.pyc
__init__.cpython-38.pyc
但是,如何让 python
复制并粘贴这些 DLL
?我可以在我的 setup.py
文件中添加一些东西吗?
编辑: 根据@ead 的评论,setup.py
可以更新为以下内容以自动将 DLL 复制到正确的文件夹(感谢@ead!) :
import os
from setuptools import find_packages, setup
import numpy as np
from Cython.Build import cythonize
from Cython.Distutils import build_ext
include_path = [
np.get_include(),
]
ext_modules = cythonize("pyembree/*.pyx", language_level=3, include_path=include_path)
for ext in ext_modules:
ext.include_dirs = include_path
ext.libraries = [
"pyembree/embree2/lib/embree",
"pyembree/embree2/lib/tbb",
"pyembree/embree2/lib/tbbmalloc",
]
setup(
name="pyembree",
version="0.1.6",
cmdclass={"build_ext": build_ext},
ext_modules=ext_modules,
zip_safe=False,
packages=find_packages(),
include_package_data=True,
package_data={"pyembree": ["*.cpp", "*.dll"]},
)
我可以在 Cython 中使用 extern __declspec(dllimport)
吗?我正在尝试将 embree
包装在 Windows 中,但我不确定我是否可以在 Cython 中动态地 link。
我阅读了 this SO post,它非常适合直接更改 C/C++ 和 header 文件,但我不确定如何在 .pxd
中实现它文件。
例如,Embree 2.17.7 x64 header rtcore.h
将 RTCORE_API
定义为
#ifndef RTCORE_API
#if defined(_WIN32) && !defined(EMBREE_STATIC_LIB)
# define RTCORE_API extern "C" __declspec(dllimport)
#else
# define RTCORE_API extern "C"
#endif
#endif
但是,这些在 pyembree pxd file rtcore.pxd
. This seems consistent with the Cython docs 中使用它们的函数签名被遗漏了,
Leave out any platform-specific extensions to C declarations such as __declspec()
但是,即使我通过更改行
将 pyembreesetup.py
文件指向我下载的 embree DLL
ext.libraries = ["embree"]
至
ext.libraries = [""C:/Program Files/Intel/Embree v2.17.7 x64/bin/embree""]
我仍然遇到 3 个 linking 错误:
mesh_construction.obj : error LNK2001: unresolved external symbol __imp_rtcMapBuffer
mesh_construction.obj : error LNK2001: unresolved external symbol __imp_rtcNewTriangleMesh
mesh_construction.obj : error LNK2001: unresolved external symbol __imp_rtcUnmapBuffer
build\lib.win-amd64-3.8\pyembree\mesh_construction.cp38-win_amd64.pyd : fatal error LNK1120: 3 unresolved externals
我从 __imp_
相关的 linker 错误是由于未找到 DLL。但是在rtcore_geometry.h
中可以看到是这样定义的:
在rtcore_geometry.pxd
中定义为:
唯一的区别是 .pxd
文件的签名中不包含 RTCORE_API
。
有谁知道我如何解决这个问题以便 pyembree
能够构建?
EDIT: 还需要注意的是,我已经添加了
# distutils: language=c++
我所有的 .pyx
和 .pxd
文件。
更新: 将 embree.lib
文件添加到我的本地 pyembree/embree2
文件夹并将 setup.py
更新为
ext.libraries = ["pyembree/embree2/*"]
允许代码通过
编译py setup.py build_ext -i
但是,这些包没有加载:
>>> import pyembree
>>> from pyembree import rtcore_scene
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: DLL load failed while importing rtcore_scene: The specified module could not be found.
我需要在 setup.py
中定义“子包”吗?这是我现在的 setup.py
:
from setuptools import find_packages, setup
import numpy as np
from Cython.Build import cythonize
from Cython.Distutils import build_ext
include_path = [np.get_include()]
ext_modules = cythonize(
'pyembree/*.pyx',
language_level=3,
include_path=include_path)
for ext in ext_modules:
ext.include_dirs = include_path
ext.libraries = [
"pyembree/embree2/*",
]
setup(
name="pyembree",
version='0.1.6',
cmdclass = {"build_ext": build_ext},
ext_modules=ext_modules,
zip_safe=False,
packages=find_packages(),
include_package_data = True
)
并且目录结构如下(pyembree
是我项目的.venv\lib\site-packages
文件夹中的top-level文件夹):
pyembree
│ .authors.yml
│ .gitignore
│ .mailmap
│ AUTHORS
│ CHANGELOG.rst
│ LICENSE
│ MANIFEST.in
│ pyproject.toml
│ README.rst
│ setup.py
│
├───build
│ └───temp.win-amd64-3.8
│ └───Release
│ └───pyembree
│ mesh_construction.cp38-win_amd64.exp
│ mesh_construction.cp38-win_amd64.lib
│ mesh_construction.obj
│ rtcore.cp38-win_amd64.exp
│ rtcore.cp38-win_amd64.lib
│ rtcore.obj
│ rtcore_scene.cp38-win_amd64.exp
│ rtcore_scene.cp38-win_amd64.lib
│ rtcore_scene.obj
│ triangles.cp38-win_amd64.exp
│ triangles.cp38-win_amd64.lib
│ triangles.obj
│
├───pyembree
│ │ mesh_construction.cp38-win_amd64.pyd
│ │ mesh_construction.cpp
│ │ mesh_construction.h
│ │ mesh_construction.pyx
│ │ rtcore.cp38-win_amd64.pyd
│ │ rtcore.cpp
│ │ rtcore.pxd
│ │ rtcore.pyx
│ │ rtcore_geometry.pxd
│ │ rtcore_geometry_user.pxd
│ │ rtcore_ray.pxd
│ │ rtcore_scene.cp38-win_amd64.pyd
│ │ rtcore_scene.cpp
│ │ rtcore_scene.pxd
│ │ rtcore_scene.pyx
│ │ triangles.cp38-win_amd64.pyd
│ │ triangles.cpp
│ │ triangles.pyx
│ │ __init__.pxd
│ │ __init__.py
│ │
│ ├───embree2
│ │ embree.lib
│ │ rtcore.h
│ │ rtcore.isph
│ │ rtcore_builder.h
│ │ rtcore_geometry.h
│ │ rtcore_geometry.isph
│ │ rtcore_geometry_user.h
│ │ rtcore_geometry_user.isph
│ │ rtcore_ray.h
│ │ rtcore_ray.isph
│ │ rtcore_scene.h
│ │ rtcore_scene.isph
│ │ rtcore_version.h
│ │ tbb.lib
│ │ tbbmalloc.lib
│ │
│ └───__pycache__
│ __init__.cpython-38.pyc
│
└───tests
test_intersection.py
一旦我手动将 DLL
复制并粘贴到我的 .venv\Lib\site-packages
文件夹中生成的 .egg
文件夹中,代码就会正常运行:
pyembree-0.1.6-py3.8-win-amd64.egg
├───EGG-INFO
│ dependency_links.txt
│ native_libs.txt
│ not-zip-safe
│ PKG-INFO
│ SOURCES.txt
│ top_level.txt
│
└───pyembree
│ embree.dll
│ freeglut.dll
│ mesh_construction.cp38-win_amd64.pyd
│ mesh_construction.cpp
│ mesh_construction.py
│ rtcore.cp38-win_amd64.pyd
│ rtcore.cpp
│ rtcore.py
│ rtcore_scene.cp38-win_amd64.pyd
│ rtcore_scene.cpp
│ rtcore_scene.py
│ tbb.dll
│ tbbmalloc.dll
│ triangles.cp38-win_amd64.pyd
│ triangles.cpp
│ triangles.py
│ __init__.py
│
└───__pycache__
mesh_construction.cpython-38.pyc
rtcore.cpython-38.pyc
rtcore_scene.cpython-38.pyc
triangles.cpython-38.pyc
__init__.cpython-38.pyc
但是,如何让 python
复制并粘贴这些 DLL
?我可以在我的 setup.py
文件中添加一些东西吗?
编辑: 根据@ead 的评论,setup.py
可以更新为以下内容以自动将 DLL 复制到正确的文件夹(感谢@ead!) :
import os
from setuptools import find_packages, setup
import numpy as np
from Cython.Build import cythonize
from Cython.Distutils import build_ext
include_path = [
np.get_include(),
]
ext_modules = cythonize("pyembree/*.pyx", language_level=3, include_path=include_path)
for ext in ext_modules:
ext.include_dirs = include_path
ext.libraries = [
"pyembree/embree2/lib/embree",
"pyembree/embree2/lib/tbb",
"pyembree/embree2/lib/tbbmalloc",
]
setup(
name="pyembree",
version="0.1.6",
cmdclass={"build_ext": build_ext},
ext_modules=ext_modules,
zip_safe=False,
packages=find_packages(),
include_package_data=True,
package_data={"pyembree": ["*.cpp", "*.dll"]},
)