#c# #c #dll #file-io #uwp
#c# #c #dll #file-io #uwp
Вопрос:
Я посмотрел в Интернете, чтобы узнать, сталкивался ли кто-нибудь с этой проблемой, но ничего не нашел.
Итак, я пытаюсь использовать C DLL в приложении C # UWP. В этой DLL есть файл журнала, который открывается в начале кода со следующей функцией:
#include <string>
#include <iostream>
using namespace std;
int Logger::set(string file_name, bool clear_log) {
_file_stream.exceptions(ofstream::failbit | ofstream::badbit);
try {
_file_stream.open(file_name, ios_base::out | (clear_log ? ios_base::trunc : ios_base::app));
}
catch (ofstream::failure) {
return -1;
}
_file_stream << "";
return 0;
}
Вот код класса Logger:
class Logger {
private:
std::ofstream _file_stream;
public:
Logger() {};
~Logger() { _file_stream.close(); };
int set(std::string file_name, bool clear_log);
}
Теперь этот код отлично работает, когда я использую DLL в автономном режиме. Но при вызове через приложение UWP функция open() выдает исключение ofstream::failure со словами:
ios_base::failbit set: ошибка потока iostream
Сначала я подумал, что это связано со странными политиками прав доступа UWP, но после отладки file_name
указывает на правильную папку пакета в AppData, поэтому здесь должно быть нормально записать файл.
В чем может быть проблема?
РЕДАКТИРОВАТЬ: я обнаружил, что по какой-то причине C file API работает так, как ожидалось. То есть следующий код успешно создает файл:
#include <iostream>
using namespace std;
int Logger::set(string file_name, bool clear_log) {
FILE* test = fopen(file_name.c_str(), clear_log ? "w" : "a");
if(!test)
{
return -1;
}
fprintf(test, "");
return 0;
}
Комментарии:
1. Не могли бы вы сказать мне, является ли ваша DLL проектом библиотеки динамических ссылок (DLL) или проектом DLL (Universal Windows) ?
2. Это проект DLL, часть UWP — это совсем другой проект.
3. Я заметил, что вы редактируете часть описания вашего случая, так что ваша проблема решена?
4. @YanGu-MSFT на самом деле нет, потому что я построил всю свою библиотеку вокруг использования журнала в качестве объекта, подобного cout, и я не могу реорганизовать его, чтобы так же легко использовать C API.
Ответ №1:
Я сам разобрался в этом после более активной отладки. Где-то раньше в коде этот аналогичный (косвенный) вызов ofstream::open не завершался неудачей:
ofstream out("out.txt", ios_base::trunc);
И, установив точки останова в нужном месте, я смог определить, что в этом случае значение открытого режима ( ios_base::trunc
аргумент) преобразовалось в 18 (ожидаемое значение), тогда как в проблемном случае при использовании троичного оператора оно преобразовалось в странное значение 1594.
Замена троичного оператора на блок if-else решила проблему:
int Logger::set(string file_name, bool clean_log) {
_file_stream.exceptions(ofstream::failbit | ofstream::badbit);
try
{
if (clean_log)
_file_stream.open(file_name, ios_base::trunc);
else
_file_stream.open(file_name, ios_base::app);
}
catch (ofstream::failure)
{
return -1;
}
return 0;
}