Предоставить глобальную переменную C ++ в Python

Я пытаюсь получить доступ к глобальной переменной C ++ в моем коде Python, используя Cython.

Допустим, у меня есть следующий массив в моем коде C ++:

// Project.cpp
int myArr[2] = { 0, 1 };

Итак, в Cython определить указатель на myArr:

cdef extern int * myArr_ptr

Есть ли myArr_ptr действительно указывает на массив C ++? Или это просто случайное значение?

1

Решение

ОК, проблема в следующем:

Project.cpp имеет глобальный int *myArr;это не указано в Project.hи вы хотите получить к нему доступ из Cython без импорта Project.cpp,

В комментариях вы говорите:

Я не могу включить Project.cpp, потому что этот файл будет пытаться включить другие файлы, которые уже были включены, и попытается переопределить много переменных.

Как вы описали это, здесь может быть элементарная ошибка. Вы, наверное, знаете эти основные вещи, поэтому, пожалуйста, не оскорбляйте меня, когда я их поднимаю, но я просто хочу быть тщательным:

Во-первых, если ваши заголовочные файлы не защищают от множественного включения, исправьте это, и тогда вам не нужно беспокоиться о том, что «я не могу включить Project.cpp потому что этот файл будет пытаться включить другие файлы, которые уже были включены, и попытаться переопределить много переменных. «(И если у вас нет заголовочных файлов, и вы просто делаете все в файлах .cpp с явным extern операторы повсюду, не делайте этого — это плохая идея в C и C ++, задолго до того, как вы приступите к Cythonizing.)

Во-вторых, если ваш модуль предназначен для взаимодействия с .so / .dll / .dylib, Project.cpp является частью, вы должны строить не с исходным кодом для этой библиотеки, а с установленным интерфейсом. С другой стороны, если ваш модуль предназначен для непосредственного включения кода C ++, то вы иметь включать Project.cpp, Если вы используете extern объявления, ссылающиеся на вещи, в которые вы не собираетесь ссылаться, вы просто получите ошибку компоновщика — или, если вам не повезет, все будет создано, но затем произойдет сбой во время выполнения.

В-третьих, если это не глобально, вы не можете получить доступ извне Project.cpp— по причинам области действия, времени жизни или связи никакая другая переменная не может использоваться в отдельном файле реализации.

Опять же, я полагаю, что вы знаете все эти основные вещи, и я просто неправильно прочитал ваш комментарий. Там является реальный проблемный случай, когда вам нужно обернуть что-то с плохо разработанным API, который требует от вас проникновения во внутренности, и это иногда может быть сложно, и вы, вероятно, сталкивались с такой вещью, а я просто не понял как именно.

Есть три основных решения.

Во-первых, очевидно, что если вы можете создать правильный нативный API, то оборачивать этот API в Cython тривиально. И это полезно по другим причинам, в то же время. Иногда это будет слишком много времени и усилий — например, если нативная библиотека не была разработана для внешнего управления, и это масса 10-летнего устаревшего обслуживания, и единственная причина, по которой вам когда-либо придется обернуться это текущий проект Cython, вы можете не захотеть его очищать. Или, если это быстро меняющаяся библиотека, с которой вам нужно быть в курсе событий и не иметь контроля над источниками, разветвление и синхронизация могут стать кошмаром. И так далее. Но если в вашем случае нет такой причины, это правильный ответ. Если вы можете просто cdef extern from "project.h"все легко.

Вы можете сделать более простую версию этого, создав «shim API» на собственном уровне, создав отдельный .h файлы с соответствующими объявлениями extern, function и type для различных функций и типов, которые вы должны использовать из внутренних компонентов. Тогда вы можете просто cdef extern from "project_extras.h",

Наконец, вы всегда можете написать явное cdef extern заявления для чего-либо, не сообщая Cython, откуда все это происходит. Cython превратит это в соответствующие нативные внешние элементы в сгенерированном коде, и если вы все сделаете правильно, это сработает. Здесь есть некоторые недостаткидокументы объяснить все преимущества cdef extern from что ты сдашься. Вкратце, ваши объявления Cython должны точно соответствовать нативным объявлениям; в противном случае, вместо того, чтобы автоматически исправлять или вызывать приятную ошибку на этапе Cython, вы получите непостижимое сообщение об ошибке от компилятора C, ссылающееся на нечитаемый сгенерированный Cython-код C вместо вашего фактического кода или, что еще хуже, кода это компилирует, но делает не то.

Для случая простого int * или же int [] ценность, все это едва ли имеет значение, потому что это не нуждается в какой-либо интерпретации; равнина cdef extern должно быть просто отлично.

4

Другие решения

Других решений пока нет …