У меня есть приложение C++, которое называет SQLite's (SQLite находится в C) sqlite3_exec (), который в свою очередь может назвать мою функцию обратного вызова реализованной в C++. SQLite компилируется в статическую библиотеку.
Если исключение выйдет из моего обратного вызова, то это распространит безопасно через код C SQLite к коду C++, звоня sqlite3_exec ()?
Я думаю, что это зависит от компилятора. Тем не менее, бросание исключения в обратном вызове было бы очень плохой идеей. Либо оно не будет работать без работы, либо код C в библиотеке SQLite не сможет обрабатывать его. Подумайте, что если это какой-то код в SQLite:
{
char * p = malloc( 1000 );
...
call_the_callback(); // might throw an exception
...
free( p );
}
Если исключение «работает», код C не имеет возможности охватить его, а P никогда не будет освобожден. То же самое касается любых других ресурсов, которые могут выделить библиотеку.
Это не вариант. Вам придется p / вызывать функцию в DLL, которая была сгенерирована MASM или записана в неуправляемом C / C ++, используя встроенную сборку или внутрисину. Или используйте компилятор C ++ / CLI и генерируйте код смешанного режима с управлением #PRAGMA.
Остерегайтесь, что вы теперь больше не можете зависеть от компилятора JIT, генерируя любой код платформы для операционной системы. Используйте Project + Properties, создайте вкладку, цель платформы, чтобы заставить архитектуру соответствовать вашу неуправляемый код.
Посмотрите на CUDA для управляемого кода GPU.
-121--3339028-, который был действительно интересным вопросом, и я проверял его из любопытства. На моей ОС X W / GCC 4.2.1 Ответ был да. Это работает отлично. Я думаю, что настоящий тест будет использовать GCC для C ++ и некоторых других (MSVC?, LLVM?) Для расставания C и посмотрим, работает ли она.
Мой код:
Callb.h:
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*t_callb)();
void cfun(t_callb fn);
#ifdef __cplusplus
}
#endif
Callb.c:
#include "callb.h"
void cfun(t_callb fn) {
fn();
}
main.cpp:
#include <iostream>
#include <string>
#include "callb.h"
void myfn() {
std::string s( "My Callb Except" );
throw s;
}
int main() {
try {
cfun(myfn);
}
catch(std::string s) {
std::cout << "Caught: " << s << std::endl;
}
return 0;
}
Если ваш обратный вызов вызывается из SQLite, из того же потока, из которого вы называете SQLite3_EXEC () a your qualthstack, должны быть пойманы более высоким уровнем.
Тестирование этого самостоятельно должно быть простым, нет?
[править] После того, как я выпал немного больше, я обнаружил, что стандарт C ++ несколько расплывчан на том, что поведение функция C ++ вызывается из C, должна иметь при броске исключения.
Вы обязательно обязательно используете механизм обработки ошибок, ожидает API. В противном случае вы в основном сам API в неопределенном состоянии, и любые дополнительные звонки могут потенциально повернуть / сбой.
SQLite ожидает, что вы вернете ошибку SQLite_abort на ошибку и код возврата 0 без ошибок. Таким образом, вы должны сделать завернуть весь обратный вызов C ++ в попытке поймать . Затем в Catch верните код ошибки SQLite SQLite_abort, в противном случае нулевой.
Проблемы будут возникать, если вы обходите возвращение через SQLite, так как он не будет освобожден / завершить код, который он выполняет после возвращения от вашего обратного вызова. Это приведет к неисследованным проблемам потенциально некоторые из которых могут быть очень неясными.
Уже есть протокол для обратного вызова, чтобы прервать вызов API. Из Документы :
Если возвращает обратный вызов sqlite3_exec () ненулевая, обычная, sqlite3_exec () Возвращает sqlite_abort, не вызывая обратный вызов снова и без бега любые последующие операторы SQL.
Я настоятельно рекомендую вам использовать это вместо исключения.