Программист выходного дня, новичок в C ++, сражающийся с войной указателей!
Я пытаюсь закодировать в C ++ метод для извлечения данных из API, используя вектор, который передается через аргумент void * в функцию обратного вызова.
Возвращенные данные будут переданы обратно в lua, который является внешним интерфейсом, используемым в приложении. Часть lua - это не то, что меня озадачило, это проблема наполнения моей структуры данными обратного вызова.
У меня все это работало с использованием простых указателей int, но мне сказали, что это предпочтительный способ сделать это с помощью структуры, и мне предложили сделать следующее:
1 - define a struct that contains the 6 ints
2 - create an std::vector that can contain instances of the new struct
3 - pass a pointer to the vector as refcon into XPLMGetAllMonitorBoundsGlobal
inside the callback function:
4 - cast the refcon pointer back to the vector type
5 - create a new instance of the struct and fill it with the 6 ints that are passed to the callback function
6 - push that instance into the vector
7 - when XPLMGetAllMonitorBoundsGlobal returns, the vector will be filled with the bounds of all screens
8 - convert the vector into a lua-compatible thing, probably a two-dimensional array
push that array into lua
Вот код, который я придумал, сделал ли поиск в Google / Stackoverflow так близко, но, хотя код компилируется, приложение зависает или вызывает ошибки сегмента, зависит от того, что я настроил. Я думаю, что основная проблема заключается в том, как я возвращаю указатель refcon к векторному типу, слишком много ссылок / разыменований указателей, и, вероятно, есть и другие проблемы.
struct MonitorBoundsStructure // #1
{
int MonitorIndex;
int LeftBx;
int TopBx;
int RightBx;
int BottomBx;
int RefCon;
};
static void LuaReceiveMonitorBoundsOS_t(int inMonitorIndex, int inLeftBx, int inTopBx, int inRightBx, int inBottomBx, void * refcon)
{
vector<MonitorBoundsStructure*>& MonitorBounds = *reinterpret_cast<vector<MonitorBoundsStructure*> *>(refcon); #4
//vector<MonitorBoundsStructure> MonitorBounds = reinterpret_cast<vector<MonitorBoundsStructure*> *>(refcon);
//vector<MonitorBoundsStructure> MonitorBounds = *reinterpret_cast<vector<MonitorBoundsStructure> *>(refcon);
//vector<MonitorBoundsStructure> MonitorBounds = reinterpret_cast<vector<MonitorBoundsStructure> *>(refcon);
//vector<MonitorBoundsStructure>* MonitorBounds = static_cast<vector<MonitorBoundsStructure> *>(refcon);
MonitorBoundsStructure returnData; //{0,0,0,0,0,0}; #5
returnData.MonitorIndex = inMonitorIndex;
returnData.LeftBx = inLeftBx;
returnData.TopBx = inTopBx;
returnData.RightBx = inRightBx;
returnData.BottomBx = inBottomBx;
returnData.RefCon = *(int *)refcon;
MonitorBounds.push_back(&returnData); // #6
}
static int LuaXPLMGetAllMonitorBoundsOSTest()
{
//std::vector<std::shared_ptr<MonitorBoundsStructure>> MonitorBounds;
vector<MonitorBoundsStructure> MonitorBounds; // #2
XPLMGetAllMonitorBoundsOS(LuaReceiveMonitorBoundsOS_t, &MonitorBounds); // #3
int i = 0;
for (vector<MonitorBoundsStructure>::iterator it = MonitorBounds.begin(); it != MonitorBounds.end(); ++it)
{
i++;
logMsg(logToAll, string("MonitorBounds ").append(to_string(i)));
}
return 1;
}
Если я закомментирую MonitorBounds.push_back (& returnData), код, по крайней мере, попадет туда, где структура внутри обратного вызова заполнена правильными данными, я ударю стену, возвращая эту структуру обратно в вызывающую функцию, что означает мой приведение пустоты * к вектору по меньшей мере неверно.
Я оставил несколько других попыток в комментариях показать, что я пробовал.
Я близок к решению или далеко?
Решение:
Спасибо Теду Лингмо за предоставленное решение, даже за то, что он даже написал тестовый код на своей собственной системе. Моя проблема, как я подозревал, заключалась в приведении указателя на вектор. Я включил ответы как push_back, так и emplace_back (гораздо точнее).
функция обратного вызова:
static void LuaReceiveMonitorBoundsOS_e(int inMonitorIndex, int inLeftBx, int inTopBx, int inRightBx, int inBottomBx, void * refcon)
{
auto& MonitorBounds = *reinterpret_cast<vector<MonitorBoundsStructure>*>(refcon);
MonitorBoundsStructure returnData;
returnData.MonitorIndex = inMonitorIndex;
returnData.LeftBx = inLeftBx;
returnData.TopBx = inTopBx;
returnData.RightBx = inRightBx;
returnData.BottomBx = inBottomBx;
MonitorBounds.push_back(returnData);
}
и
static void LuaReceiveMonitorBoundsOS_e(int inMonitorIndex, int inLeftBx, int inTopBx, int inRightBx, int inBottomBx, void * refcon)
{
auto& MonitorBounds = *reinterpret_cast<vector<MonitorBoundsStructure>*>(refcon);
MonitorBounds.emplace_back(
MonitorBoundsStructure{
inMonitorIndex,
inLeftBx,
inTopBx,
inRightBx,
inBottomBx
}
);
}
функция вызова:
static int LuaXPLMGetAllMonitorBoundsOSTestE(lua_State *L)
{
vector<MonitorBoundsStructure> MonitorBounds;
XPLMGetAllMonitorBoundsOS(LuaReceiveMonitorBoundsOS_e, &MonitorBounds);
for (auto& m : MonitorBounds) {
std::cout << m.MonitorIndex << "\n";
}
return 1;
}