Дорогой стек обмена,
Я программирую МРТ сканер. Я не буду вдаваться в подробности, но я довольно ограничен в объеме кода, к которому у меня есть доступ, и в том, как все было настроено … неоптимально. У меня такая ситуация:
Короче говоря, моя проблема:
Это похоже на абсолютную суету управления памятью, и я подумал, что я бы попросил здесь «наилучшую практику» в этих ситуациях, так как вполне вероятно, что есть много тонких проблем, с которыми я мог бы столкнуться — и что у других может быть много соответствующей мудрости, чтобы передать. Отладка системы — это кошмар, и я не получил никакой поддержки от производителя сканера по этому вопросу.
Краткий набросок того, как я планирую действовать следующим образом:
В библиотеке .cpp:
/* In something::something() /*
/* declare a pointer to a function */
void (*fp)(int*, int, int, ...);
/* by default, the pointer points to a placeholder at compile time*/
fp = &doNothing(...);
...
/* At the appropriate time, point the pointer to the userland function, whose address is supplied as an argument to something(): /*
fp= userFuncPtr;
/* Declare memory for the user function to plonk data into */
i_arr_coefficients = (int) malloc(SOMETHING_SENSIBLE);
/* Create a pointer to that array for the userland function */
i_ptr_array=&i_arr_coefficients[0];
/* define a struct of pointers to local variables for the userland function to use*/
ptrStrct=createPtrStruct();
/* Call the user's function: */
fp(i_ptr_array,ptrStrct, ...);
CarryOnWithSomethingElse();
Смысл функции-заполнителя состоит в том, чтобы держать все как есть, если пользовательская функция не связана. Я понимаю, что это можно заменить на #DEFINE
, но хитрость или глупость компилятора может привести к странному (по крайней мере, на мой взгляд, невежественному) поведению.
В функции userland у нас будет что-то вроде:
void doUsefulThings(i_ptr_array, ptrStrct, localVariableAddresses, ...) {
double a=*ptrStrct.a;
double b=*ptrStrct.b;
double c=*localVariableAddresses.c;
double d=doMaths(a, b, c);
/* I.e. do maths using all of these numbers we've got from the different sources */
storeData(i_ptr_array, d);
/* And put the results of that maths where the C++ method can see it */
}
...
something(&doUsefulThings(i_ptr_array, ptrStrct, localVariableAddresses, ...), ...);
...
Если это так же ясно, как грязь, пожалуйста, скажите мне! Большое спасибо за Вашу помощь. И, кстати, я искренне желаю, чтобы кто-нибудь сделал открытую аппаратную / исходную систему МРТ.
* Кроме того, это основное оправдание, которое производитель использует, чтобы отговорить нас от изменения большой библиотеки в первую очередь!
У вас есть полный доступ к коду C У вас ограниченный доступ к коду библиотеки C ++. Код на C определяет функцию «doUsefullthings». Из кода C вы вызываете функцию «Something» (класс / функция C ++) с указателем на «doUseFullThings» в качестве аргумента. Теперь управление переходит в библиотеку C ++. Здесь различные аргументы выделяются памятью и инициализируются. Затем с этими аргументами вызывается doUseFullThings. Здесь управление переходит обратно к коду C. Короче говоря, основная программа (C) вызывает библиотеку (C ++), а библиотека вызывает функцию C.
Одним из требований является то, что «пользовательская функция должна иметь доступ к локальной переменной из кода C, где она вызывается». Когда вы звоните «что-то», вы даете только адрес «doUseFullThings». Не существует параметра / аргумента «что-то», которое бы захватывало адрес локальных переменных. Таким образом, doUseFullThings не имеет доступа к этим переменным.
Оператор malloc возвращает указатель. Это не было обработано должным образом (вероятно, вы пытались дать нам обзор). Вы должны заботиться, чтобы освободить это где-нибудь.
Поскольку это смесь кода на C и C ++, трудно использовать RAII (заботиться о распределенной памяти), Perfect forwarding (избегать копирования переменных), функции Lambda (для доступа к локальным вариабелям) и т. Д. В этих условиях ваш подход кажется быть способом идти.
Других решений пока нет …