C ++ Python Связывание CMake <stdin>строка 1 Ошибка ImportEn: Dynami c модуль не определяет функцию экспорта модуля - PullRequest
0 голосов
/ 28 апреля 2020

Я пытаюсь установить модуль с Python и создать расширение для обнаружения файлов полицейских c. cpp. Но после того, как я:

python3 setup.py install

установка прошла успешно. Затем:

python 
import detectc

Я получаю следующую ошибку

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define module export function (PyInit_detectc)

Файлы для воспроизведения:

setup.py

from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
import os
import platform
import subprocess
import sys
from pprint import pprint

c_module_name = "detectc"

cmake_cmd_args = []
for f in sys.argv:
    if f.startswith('-D'):
        cmake_cmd_args.append(f)

for f in cmake_cmd_args:
    sys.argv.remove(f)

class CMakeBuild(build_ext):
    def build_extensions(self):
        try:
            out = subprocess.check_output(['cmake', '--version'])
        except OSError:
            raise RuntimeError('Cannot find CMake executable')

        for e in self.extensions:
            extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(e.name)))
            cfg = 'Release'
            cmake_args = [
                    '-DPYTHON_EXECUTABLE=/home/ubuntu/anaconda3/envs/dutchman/bin/python',
                    '-DCMAKE_BUILD_TYPE=%s' % cfg,
                    '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir),
                    '-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), self.build_temp),
#                     '-DPYTHON_EXECUTABLE={}'.format(sys.executable)
                ]
            build_ext.build_extensions(self)

            cmake_args += cmake_cmd_args
            print(cmake_args)
            print(e.cmake_lists_dir)
            if not os.path.exists(self.build_temp):
                os.makedirs(self.build_temp)
            subprocess.check_call(['cmake', e.cmake_lists_dir] + cmake_args,
                                  cwd=self.build_temp)

            subprocess.check_call(['cmake', '--build', '.', '--config', cfg],
                                  cwd=self.build_temp)



class CMakeExtension(Extension):
    def __init__(self, name, cmake_lists_dir='.', **kwa):
        Extension.__init__(self, name, sources=[], **kwa)
        self.cmake_lists_dir = os.path.abspath(cmake_lists_dir)
        print(self.cmake_lists_dir)


setup(name='detectc',
      version='1.1.0',
      description='Generate displacement fields with known volume changes',
      install_requires=['numpy>=1.15.1'],
      ext_modules=[CMakeExtension(c_module_name)],
      cmdclass={'build_ext': CMakeBuild},
      )

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(detectc_)

find_package(PythonInterp 3.5 REQUIRED)

# This comes to hand if we also need to use the NumPy C API
exec_program(${PYTHON_EXECUTABLE}
             ARGS "-c \"import numpy; print(numpy.get_include())\""
             OUTPUT_VARIABLE NUMPY_INCLUDE_DIR
             RETURN_VALUE NUMPY_NOT_FOUND
            )

set(SRCS "detectc.cpp")
#add_library(detectc_ SHARED ${SRCS})
add_library(detectc_ ${SRCS})

set_target_properties(
    detectc_
    PROPERTIES
        PREFIX ""
        OUTPUT_NAME "detectc"
        LINKER_LANGUAGE CXX
    )

# Find NumPy headers
exec_program(${PYTHON_EXECUTABLE}
    ARGS "-c \"import numpy; print(numpy.get_include())\""
    OUTPUT_VARIABLE NUMPY_INCLUDE_DIR
    RETURN_VALUE NUMPY_NOT_FOUND
    )
if(NUMPY_NOT_FOUND)
    message(FATAL_ERROR "NumPy headers not found")
endif()

# Find Python headers
exec_program(${PYTHON_EXECUTABLE}
    ARGS "-c \"import sysconfig; print(sysconfig.get_paths()['include'])\""
    OUTPUT_VARIABLE PYTHON_INCLUDE_DIRS
    RETURN_VALUE PYTHON_INCLUDE_DIRS_NOT_FOUND
    )
if(PYTHON_INCLUDE_DIRS_NOT_FOUND)
    message(FATAL_ERROR "Python headers not found")
endif()


target_include_directories(detectc_ PUBLIC
    ${PYTHON_INCLUDE_DIRS}
    ${NUMPY_INCLUDE_DIR}
    )

обнаружить c. cpp

#include <python3.5/Python.h>

static PyObject* division(PyObject *self, PyObject *args);

// Exported methods are collected in a table
PyMethodDef method_table[] = {
    {"division", division, METH_VARARGS, "Method docstring"},
    {NULL, NULL, 0, NULL} // Sentinel value ending the table
};


// A struct contains the definition of a module
PyModuleDef moduledef = {
    PyModuleDef_HEAD_INIT,
    "detectc", // Module name
    "This is the module docstring",
    -1,   // Optional size of the module state memory
    method_table,
    NULL, // Optional slot definitions
    NULL, // Optional traversal function
    NULL, // Optional clear function
    NULL  // Optional module deallocation function
};


// The module init function
// PyMODINIT_FUNC PyInit__detectc(void) {
//     return PyModule_Create(&moduledef);
// }

PyMODINIT_FUNC PyInit_detectc() {
    return PyModule_Create(&moduledef);
}

// This is the definition of a method
static PyObject* division(PyObject *self, PyObject *args) {
    long dividend, divisor;
    if (!PyArg_ParseTuple(args, "ll", &dividend, &divisor)) {
        return NULL;
    }
    if (0 == divisor) {
        PyErr_Format(PyExc_ZeroDivisionError, "Dividing %d by zero!", dividend);
        return NULL;
    }
    return PyLong_FromLong(dividend / divisor);
}

Структура файла:

(---) ubuntu@---:~/robo/ext_test/Detect$ ls
CMakeLists.txt  detectc.cpp  __init __.py  setup.py

Выхода нет. Задача состоит в том, чтобы отладить и исправить, я не могу использовать повышение или около того.

...