C ++ Lua userdata возиться со значениями Mathfu с плавающей точкой - PullRequest
1 голос
/ 18 февраля 2020

Я пытаюсь использовать Mathfu :: Vector из Lua для создания векторов, но у меня возникает проблема, когда я пытаюсь извлечь пользовательские данные обратно из стека.

вот функция Я использую для определения пользовательских данных

static int vec4(lua_State *L)
{
  const float x = luaL_checknumber(L, 1);
  const float y = luaL_checknumber(L, 2);
  const float z = luaL_checknumber(L, 3);
  const float w = luaL_checknumber(L, 4);

  mathfu::Vector<float, 4> vec(x, y, z, w);
  *static_cast<mathfu::Vector<float, 4> **>(
      lua_newuserdata(L, sizeof(mathfu::Vector<float, 4> *))) = &vec;
  luaL_setmetatable(L, VECTOR_LIB_NAME);

  return 1;
}

И у меня есть функция, которая получает скалярное произведение двух векторов на основе значения self и аргумента (оба userdata)

static int dotVector(lua_State *L)
{
  mathfu::Vector<float, 4> *vecA = *static_cast<mathfu::Vector<float, 4> **>(luaL_checkudata(L, 1, VECTOR_LIB_NAME));
  mathfu::Vector<float, 4> *vecB = *static_cast<mathfu::Vector<float, 4> **>(luaL_checkudata(L, 2, VECTOR_LIB_NAME));

  LOGI("A: %f, %f, %f", vecA->x, vecA->y, vecA->z);
  LOGI("B: %f, %f, %f", vecB->x, vecB->y, vecB->z);
  float dot = mathfu::Vector<float, 4>::DotProduct(*vecA, *vecB);
  lua_pushnumber(L, dot);

  return 1;
};

вызывается из lua как

local vecA = vec4(1, 2, 3, 4)
local vecB = vec4(5, 6, 7, 8)
vecA:dot(vecB)

Но печатаемые значения сумасшедшие, как будто они преобразуют неверные данные в число с плавающей точкой

A: -8055257885499399810754615288266752.000000, 0.000000, 0.000000
B: 0.000000, 3746318080.000000, 3573.204346

Я исследовал стек и Первые два элемента, безусловно, UserData, но я, кажется, не могу копать глубже в пользовательских данных. Переменные в C ++ содержат эти значения, но я не знаю, что может быть причиной этого. Я уверен, что пользовательские данные - это не то, чего я ожидаю.

Ответы [ 2 ]

1 голос
/ 18 февраля 2020

Нет, вы сделали утечку памяти. Первой версией был указатель на выделенный объект стека (& ve c), который уничтожается после завершения функции. 2-я версия (новая mathfu :: Vector) создается должным образом в куче ... и я думаю, что вы никогда не удалите ее позже = утечка памяти.

Также попробуйте избежать static_cast указателей. Или любой принудительный актерский состав. Это добавит проблем, например, если g ++ будет использовать «строгое псевдонимы» (неявно с помощью -O3), тогда любые указатели будут прерваны. «строгое псевдонимы» предполагает, что 1 блок памяти никогда не указывается указателями другого типа. Или вы должны явно настроить компилятор, чтобы избежать этого. Вообще хорошей идеей является использование memcpy. Компиляторы понимают и оптимизируют это должным образом. Например, если вы хотите, чтобы указатель в виде символа для int32:

int32 a; 
char b[sizeof(a)]; 
memcpy(b, &a, sizeof(a));

и вместо него теперь использовали b

static_cast<char*>(&a);
0 голосов
/ 18 февраля 2020

В конце концов это оказалось глупостью, взятие ссылки с & представляется неправильным способом получить указатель на объект. Я изменил свой векторный код инициализации на

static int vec4(lua_State *L)
{
  const float x = luaL_checknumber(L, 1);
  const float y = luaL_checknumber(L, 2);
  const float z = luaL_checknumber(L, 3);
  const float w = luaL_checknumber(L, 4);

  *static_cast<mathfu::Vector<float, 4> **>(
      lua_newuserdata(L, sizeof(mathfu::Vector<float, 4> *))) = new mathfu::Vector<float, 4>(x, y, z, w);;
  luaL_setmetatable(L, VECTOR_LIB_NAME);

  return 1;
}

И все это работает, я предполагаю, что, потому что, когда я использую new, он дает мне «реальный» адрес указателя вместо ссылки? Живи и учись.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...