Короче говоря, вопрос заключается в том, чтобы передать объектИспользование Эйген :: Карта <Эйген :: MatrixXd> в качестве аргумента функции типа Эйгена :: MatrixXd
Eigen::Map<Eigen::MatrixXd>
к функции, ожидающей
Eigen::MatrixXd
объект.
Longer история:
У меня есть эта C++ функция объявления
void npMatrix(const Eigen::MatrixXd &data, Eigen::MatrixXd &result);
вместе с этой реализации
void npMatrix(const Eigen::MatrixXd &data, Eigen::MatrixXd &result)
{
//Just do s.th. with arguments
std::cout << data << std::endl;
result(1,1) = -5;
std::cout << result << std::endl;
}
Я хочу, чтобы вызвать эту функцию из питона с помощью numpy.array как аргументы. Для этого я использую функцию-обертку, написанный на C++
void pyMatrix(const double* p_data, const int dimData[],
double* p_result, const int dimResult[]);
, которая принимает указатель на данные, размер массива данных, указатель на результат, а размер результирующего массива. Указатель данных указывает на постоянный патч памяти, поскольку данные не должны изменяться, тогда как патч памяти, зарезервированный для результата, записывается. Реализация функции
void pyMatrix(const double *p_data, const int dimData[], double *p_result, const int dimResult[])
{
Eigen::Map<const Eigen::MatrixXd> dataMap(p_data, dimData[0], dimData[1]);
Eigen::Map<Eigen::MatrixXd> resultMap(p_result, dimResult[0], dimResult[1]);
resultMap(0,0) = 100;
npMatrix(dataMap, resultMap);
}
определяет Eigen :: Map для данных и результатов соответственно. A Eigen :: Map позволяет получить доступ к необработанной памяти как к виду Eigen :: Matrix. DataMap имеет тип
<const Eigen::MatrixXd>
поскольку связанная память считывается только; resultMap в отличие от этого типа
<Eigen::MatrixXd>
так как он должен быть доступен для записи. Линия
resultMap(0,0) = 100;
показывает, что resultMap записывается на бумаге. При передаче dataMap в npMatrix(), где ожидается работа const Eigen :: MatrixXd, я не смог найти способ передать resultMap таким же образом. Я уверен, проблема связана с тем, что первый аргумент npMatrix является const, а второй - нет. Возможное решение, которое я нашел, чтобы определить
Eigen::MatrixXd resultMatrix = resultMap;
и передать эту resutlMatrix в npMatrix(). Однако, я думаю, это создает копию и, следовательно, убивает красивое отображение памяти Eigen :: Map. Так что мой вопрос.
Есть ли способ передать Eigen: Map для функции, которая ожидает не const const Eigen :: MatrixXd?
В качестве побочного примечания: я мог бы изменить npMatrix, чтобы ожидать Eigen :: Map, но поскольку в реальном проекте функции уже существуют и протестированы, я бы не стал их раздражать.
Чтобы завершить этот вопрос, вот файл питон вызвать pyMatrix()
import ctypes as ct
import numpy as np
import matplotlib.pyplot as plt
# Load libfit and define input types
ct.cdll.LoadLibrary("/home/wmader/Methods/fdmb-refactor/build/pyinterface/libpyfit.so")
libfit = ct.CDLL("libpyfit.so")
libfit.pyMatrix.argtypes = [np.ctypeslib.ndpointer(dtype=np.float64, ndim=2),
np.ctypeslib.ndpointer(dtype=np.int32, ndim=1),
np.ctypeslib.ndpointer(dtype=np.float64, ndim=2, flags='WRITEABLE'),
np.ctypeslib.ndpointer(dtype=np.int32, ndim=1)
]
data = np.array(np.random.randn(10, 2), dtype=np.float64, order='F')
result = np.zeros_like(data, dtype=np.float64, order='F')
libfit.pyMatrix(data, np.array(data.shape, dtype=np.int32),
result, np.array(result.shape, dtype=np.int32))
Спасибо за ваш ответ. Я согласился с этим, так как считаю, что в целом это хорошее решение. Как я уже сказал в вопросе, я не хочу менять интерфейс функции для вызова. Поэтому мое решение - создать необходимую мне карту. Это приводит к трате памяти и времени процессора, но по сравнению с остальной частью программы это не имеет значения. – ReedWood
Спасибо! Я подумал еще об этом, и я думаю, что нашел другой ответ, который будет делать именно то, что вы просите, и не изменяйте объявление функции. Я уточню свой ответ! –
Прошло 18 месяцев, но у SO так много полезной информации. Здесь 'new (& a)' является версией места размещения и, таким образом, явным образом отбрасываю с объекта «Карта» на «Матрица», я полагаю (пожалуйста, поправьте меня, если я ошибаюсь). Я предполагаю, что изменение размера, на которое вы ссылаетесь, состоит в том, что 'a' не является владельцем данных, поэтому не может присваивать ему другую матрицу, используя, например, присваивание' operator = '. Я делаю это, отслеживая владение данными - изначально 'a' может не владеть данными, но перед назначением я изменяю его размер, когда он НЕ является владельцем или текущий размер не является правильным. – NameRakes