Я хочу обернуть динамически связанную библиотеку c, с которой связаны все модули Cython.Проблема в том, что я получаю ошибку сегментации.Я читал, что переменные, которые выставляются для Cython через выражение extern, не одинаковы для каждого модуля.Например, вы не можете манипулировать int в одном модуле и видеть измененный int в другом модуле.Я думаю, что это причина моих ошибок сегментации.
Вот мой реальный пример:
Получите репозиторий jrtk под https://bitbucket.org/stueker/jrtk/src/master/. Я ссылаюсь на созданную библиотекукогда вы строите проект с помощью следующих команд терминала:
mkdir build
cmake ..
make
Я поместил следующие файлы в папку рядом с репозиторием.
setup.py :
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
)
CMakeLists.txt :
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}")
itfMain.pyx : Tcl_Interp
является структурой, а interp
является глобальным указателемк такой структуре.
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"])
itf.pyx :
from c_itfMain cimport Itf_Lib_Init
def jrtk_Init():
rv = Itf_Lib_Init(0, NULL)
c_itfMain.pxd :
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
Я скомпилировал этот код Cython с помощью: python3 setup.py build_ext --inplace
test.py :
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)
Если вы измените значение itf.jrtk_Init()
на itfMain.jrtk_Init()
, то ошибки сегментации не произойдет.В моей голове есть эта библиотека с ее функциями и глобальной переменной, которые имеют одинаковое значение из каждого модуля.Если один модуль инициирует изменение одного var, все модули будут знать.Я должен ошибаться с этим предположением, но что происходит и как исправить / обойти это?
Небольшой побочный вопрос.Есть ли разница между TypeInfo tagsInfo
и cdef TypeInfo tagsInfo
в файле pxd?
Я думаю, что у меня есть похожая проблема, как у этого парня (https://groups.google.com/forum/#!topic/cython-users/GAAPYb2X304),, но у меня уже есть динамически связанная библиотека.