如何从 Cython 中的另一个文件调用 C++ 函数?

问题描述 投票:0回答:1

我已经编写了一个函数来修剪 C++ 中字符串中的空格,我希望从另一个文件中调用它。整个过程是使用 Cython 包装器从 Python 脚本调用的

如果我不在main.cpp中调用trim,程序就会运行;如果这样做,我会收到运行时错误

Traceback (most recent call last):
  File "/home/jeff/projects/c/bfg/trim_test/trim_test.py", line 1, in <module>
    import trim_binder
ImportError: ./libmain.so: undefined symbol: _Z4trimRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

对代码量表示歉意;我已经尽可能地修剪它了。可以用

克隆它
git clone https://[email protected]/psionman/test_trim.git

main.h

#ifndef TEST_TRIM_H
#define TEST_TRIM_H

#include <iostream>

std::string testTrim(std::string);

#endif

main.cpp

#include <iostream>
#include "trim.h"

std::string testTrim(std::string line) {
  std::string trimmed {};
  trimmed = line;
  trimmed = trim(line);
  return trimmed;
}

修剪.h

#ifndef TRIM_STRINGS_H
#define TRIM_STRINGS_H

std::string& trim(std::string& s);

#endif

修剪.cpp #包括 #include“trim.h”

    // trim from left
    inline std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v")
    {
        s.erase(0, s.find_first_not_of(t));
        return s;
    }

    // trim from right
    inline std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v")
    {
        s.erase(s.find_last_not_of(t) + 1);
        return s;
    }

    // trim from left & right
    inline std::string& trim(std::string& s, const char* t = " \t\n\r\f\v")
    {
        return ltrim(rtrim(s, t), t);
    }

trim_test.py

import trim_binder

line = '  AAA BB  CC E   '
trimmed = trim_binder.get_trimmed_text(line)
print(f'In trim_test: {trimmed.replace(" ", ".")}')

trim_wrapper.pyx

from libcpp.string cimport string

cdef extern from 'main.h':
    string testTrim(char* input_text)

def get_trimmed_text(path):
    input_text = str.encode(str(path))
    py_bytes_object = input_text
    cdef string s = py_bytes_object

    raw_trimmed = testTrim(py_bytes_object)
    trimmed = raw_trimmed.decode()
    return trimmed

编译使用invoke

任务.py 导入调用

WRAPPER_NAME = 'trim_wrapper.cpp'
BINDER = 'trim_binder'  # .pyx file name
C_FILE = 'main'
compile_files = ['main', 'trim']


@invoke.task()
def build_c_function(c):
    """Build the shared library for the sample C++ code"""

    files = [file + '.cpp' for file in compile_files]
    files_str = ' '.join(files)
    invoke.run(
        f'g++ -O3 -Wall -Werror -shared -std=c++11 -fPIC {files_str} '
        '-I . '
        f'-o lib{C_FILE}.so '
    )
    print('c function build complete')


def compile_python_module(cpp_name, extension_name):
    invoke.run(
        'g++ -O3 -Wall -Werror -shared -std=c++11 -fPIC '
        '`python3 -m pybind11 --includes` '
        '-I . '
        '{0} '
        '-o {1}`python3-config --extension-suffix` '
        f'-L. -l{C_FILE} -Wl,-rpath,.'.format(cpp_name, extension_name)
    )


@invoke.task(build_c_function)
def build_cython(c):
    """Build the cython extension module"""
    invoke.run(f'cython --cplus -3 {BINDER}.pyx -o {WRAPPER_NAME}')
    compile_python_module(WRAPPER_NAME, BINDER)
    print('cython build complete')

这是 libmain.so

的符号列表
                 w __cxa_finalize@GLIBC_2.2.5
                 w __gmon_start__
                 U __gxx_personality_v0@CXXABI_1.3
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U _Unwind_Resume@GCC_3.0
0000000000001140 T _Z8testTrimNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
                 U _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE10_M_disposeEv@GLIBCXX_3.4.21
                 U _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_M_assignERKS4_@GLIBCXX_3.4.21
                 U _ZSt21ios_base_library_initv@GLIBCXX_3.4.32

并且这是 **trim_binder.cpython-311-x86_64-linux-gnu.so 符号列表的链接 ** 相当长

c++ cython
1个回答
0
投票

main.cpp
中,您没有包含标准库头文件
<string>
(这是字符串定义所在的位置)。您包括
<iostream>
。这很可能包括 <string> 中的
some
,但可能不是全部,并且某些位可能仅被前向声明。

我不确定这是否是完整的问题,但这肯定是一个错误。

© www.soinside.com 2019 - 2024. All rights reserved.