我想包装一个动态链接的c库,所有cython模块都链接在一起。问题是我遇到了分段错误。我读到通过extern语句向cython公开的变量对于每个模块都不相同。例如,您无法在一个模块中操作int并在另一个模块中查看更改的int。 我认为这是我的分段错误的原因。
这是我的真实世界的例子:
在https://bitbucket.org/stueker/jrtk/src/master/下获取jrtk回购。 我链接到使用以下终端命令构建项目时创建的库:
GAC
我将以下文件放在回购邮件旁边的文件夹中。
setup.py :
WMI
的CMakeLists.txt :
mkdir build
cmake ..
make
itfMain.pyx :
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
import os
import shutil
import subprocess
import sys
def find_tcl():
build_path = "build"
try:
os.mkdir(build_path)
except FileExistsError:
print("build already exists")
cmake_cache = "CMakeCache.txt"
tcl_include = "TCL_INCLUDE_PATH"
separator = ":PATH="
if sys.platform.startswith('win'):
shell = True
else:
shell = False
cmake_cmd = ["cmake", ".."]
print("################### Calling CMAKE ###################")
retCode = subprocess.check_call(cmake_cmd, cwd=build_path, stderr=subprocess.STDOUT, shell=shell)
print("################### CMAKE returned ###################")
text = open(os.path.join(build_path, cmake_cache)).read()
start = text.find(tcl_include)
include_path = text[start:text.find(os.linesep, start)]
return include_path.replace(tcl_include, "").replace(separator, "").strip()
jrtk_root = "/home/simon/janus/jrtk"
def declare_cython_extensions(source_path):
libs = ["janus"]
lib_dirs = [jrtk_root + os.path.sep + "build"]
postfix = "/include"
base_dir = jrtk_root + os.path.sep + "source"
(path, dirs, _) = next(os.walk(base_dir))
include_dirs = [os.path.join(path, d) + postfix for d in dirs]
include_dirs.extend([base_dir, find_tcl()])
extension_list = []
for (path, folders, files) in os.walk(source_path):
for f in files:
if f.endswith(".pyx"):
ext = Extension(f.replace(".pyx", ""),
[os.path.join(path, f)],
libraries=libs,
library_dirs=lib_dirs,
include_dirs=include_dirs,
define_macros=[("DISABLE_TK", None),
("DISABLE_READLINE", None),
# In TCL8.6 deprecated and needs this flag to activate
("USE_INTERP_ERRORLINE", None)]
)
extension_list.append(ext)
return extension_list
extensions = declare_cython_extensions(".")
ext_modules = cythonize(extensions)
setup(
name='Global setup',
ext_modules=ext_modules
)
是结构,cmake_minimum_required( VERSION 3.5 )
project( JRTK_CYTHON )
set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/cmake )
set ( INCLUDE_DIRECTORIES "")
find_package(TCL 8.5 REQUIRED)
list(APPEND INCLUDE_DIRECTORIES "${TCL_INCLUDE_PATH}")
是指向这种结构的全局指针。
Tcl_Interp
itf.pyx :
interp
c_itfMain.pxd :
from c_itfMain cimport Tcl_Interp, Itf_Lib_Init, interp, ClientData
cdef extern from "../jrtk/source/itf/include/itf/itf.h":
ctypedef struct TypeInfo:
pass
cdef extern from "../jrtk/source/itf/source/itf.c":
cdef int itfCreate(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
cdef extern from "../jrtk/source/models/source/tags.c":
TypeInfo tagsInfo
def jrtk_Init():
rv = Itf_Lib_Init(0, NULL)
def tagsTest():
print("Hello")
print(interp.errorLine)
rv = itfCreate(&tagsInfo, interp, 2, ["Tags", "tagTest"])
我通过以下方式编译此cython代码:from c_itfMain cimport Itf_Lib_Init
def jrtk_Init():
rv = Itf_Lib_Init(0, NULL)
test.py :
cdef extern from "../jrtk/source/itf/source/itfMain.c":
cdef int Itf_Lib_Init(int argc, char ** argv)
cdef Tcl_Interp *interp
cdef extern from "../jrtk/source/itf/include/itf/itf.h":
ctypedef void*ClientData
cdef extern from "/usr/include/tcl.h":
cdef struct Tcl_Interp:
char *result
void (*freeProc)(char *blockPtr)
int errorLine
此脚本将失败并显示以下输出:
python3 setup.py build_ext --inplace
如果您将import itfMain
import itf
itf.jrtk_Init()
itfMain.tagsTest()
更改为# ===========================================================================
# ____ ____ _____ _
# |__ || _ \|_ _| |
# | || |_| | | | | |/ | V6.0.0, n/a
# | || _ < | | | < ------------------------------------------------
# | ||_| |_| |_| |_|\_| Karlsruhe Institute of Technology, Germany
# _| | JANUS Recognition Carnegie Mellon University, USA
# \__/ Toolkit
# (c) 1993-2017
# ===========================================================================
started library: on desktop.3573, Di 15. Mai 21:18:24 CEST 2018
Janus Binary:
using lib: ./lib
using lib: /home/simon/janus/janus_lt/gui-tcl
using lib: /home/simon/janus/janus_lt/tcl-lib
using lib: /usr/lib
using lib: /usr/lib/tcltk
using lib: /usr/lib/tcltk/tcl8.6
using lib: /usr/lib/tcltk/x86_64-linux-gnu
using lib: /usr/local/lib/tcltk
using lib: /usr/local/share/tcltk
using lib: /usr/share/tcltk
using lib: /usr/share/tcltk/tcl8.6
using env: TCL_LIBRARY=/usr/lib/tcl8.6
using env: JANUS_LIBRARY=/home/simon/janus/jrtk/library
INFO : Using doParallelServer function
INFO : This machine (desktop) is running Linux 4.13.0-41-generic (x86_64) with Tcl 8.6
executing library
# ============================= {Main Program} ==============================
Hello
Segmentation fault (core dumped)
,则不会发生分段错误。
在我的脑海中有这个c lib,它的函数和全局变量都具有来自每个模块的相同值。如果一个模块触发对一个var的更改,则所有模块都会知道。我不得不对这个假设做错,但是发生了什么以及如何解决/解决它?
小问题。 pxd文件中的itf.jrtk_Init()
和itfMain.jrtk_Init()
之间是否存在差异?
我认为我有一个类似于这个人(https://groups.google.com/forum/#!topic/cython-users/GAAPYb2X304)的类似问题,但我已经有一个动态链接的库。