Передача glm.mat4 из Python обратно в C ++ (glm :: mat4) - PullRequest
0 голосов
/ 21 июня 2020

У меня есть приложение boost python, которое экспортирует класс в Python, выполняет вычисления и возвращает результат обратно в C ++:

import engine # c++ library
import glm # pyglm

class Game(engine.Application):
    def __init__(self):
        engine.Application.__init__(self, title, fullscreen)
        self.shader = engine.Shader();
        self.shader.setup("shader.vs", "shader.fs")
        self.shader.setMat4("model", glm.mat4(1.0)
    def update(self):
        ...

Среди других классов шейдер оборачивается и экспортировано из C ++ следующим образом:

struct ShaderWrap : Shader, boost::python::wrapper<Shader>
{
  int setup(const char* vertexPath, const char* fragmentPath)
  {
    return Shader::setup(vertexPath, fragmentPath);
  }
  int setMat4(std::string name, glm::mat4 mat)
  {
    return Shader::setMat4(name, mat);
  }
};

...

BOOST_PYTHON_MODULE(engine)
{
  namespace python = boost::python;

  ...

  python::class_<ShaderWrap, boost::noncopyable>("Shader")
    .def("setup", &Shader::setup)
    .def("setMat4", &Shader::setMat4)
    ;

  ...
}

Приложение работает нормально до вызова self.shader.setMat4, и я получаю сообщение об ошибке:

Boost.Python.ArgumentError: Python argument types in
    StaticShader.setMat4(StaticShader, str, glm::detail::tmat4x4)
did not match C++ signature:
    setMat4(StaticShader {lvalue}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, glm::mat<4, 4, float, (glm::qualifier)0>)

Я пытался передать значение mat4 как float * обратно в C ++ безуспешно. Я также пробовал вызывать value_ptr(mat4), который возвращает c_void_p, но компилятор жалуется, что c_void_p и void* не одного типа (также пробовал различные попытки кастинга с помощью библиотеки ctypes). этот вопрос и этот вопрос - это в основном одна и та же проблема, но я потерялся в реализации.

В документации PyGLM разработчик говорит, что библиотека написана на C ++. Итак,

Каким будет возможный способ передать значение glm.mat4 в C ++, чтобы интерпретировать его как значение glm::mat4?

Я хочу передать glm.mat4, такой как матрица представления, обновлявшаяся функцией обновления кода Python обратно на C ++ для дальнейшего использования, и надеялся, что будет довольно простой интерфейс между библиотекой pyGLM / библиотекой GLM через boost :: python. Заранее спасибо.

1 Ответ

0 голосов
/ 01 июля 2020

Закончил обращение к разработчику по поводу этой проблемы, и там был ответ:

Вот как объекты матрицы выглядят в коде C ++:

template<int C, int R, typename T>
struct mat {
    PyObject ob_base;
    uint8_t info;
    glm::mat<C, R, T> super_type;
};

Скорее всего, почему это не так. вполне совместим с матрицами glm.

Если вы используете последнюю версию PyGLM, value_ptr(mat4) должен возвращать объект LP_c_float, т.е. float*. Я уверен, что есть способ передать такой указатель в boost :: python, хотя, как я уже сказал, я не знаю, как.

Технически вы можете преобразовать указатель в целое число, перенесите это и верните обратно в float*. Вы можете получить адрес указателя, используя:

int.from_bytes(ptr, "little")

В качестве альтернативы вы можете просто отправить объект байтов.

as_bytes = bytes(mat4)

Или в виде кортежа:

as_tuple = mat4.to_tuple()

Или как массив numpy (который, кажется, имеет собственный модуль boost :: python :: numpy):

np_arr = numpy.array(mat4)

Мне удалось получить правильный результат, передав адрес памяти в виде int* обратно в C ++, который затем произвел некоторую нарезку, чтобы вернуть его в glm::mat4, но я нашел это решение слишком запутанным и закончил упаковкой класс glm::mat4 вручную (см. { ссылка } базовый c пример того, как этого добиться).

...