Python 3.8.0a3 failed to get the Python codec of the filesystem encoding - cpython

When I call the embedded python from my c++ app, the application crashes. Something in _PyCodec_Lookup is not working. Debugging seems to indicate the error comes from this line in file codecs.c:
PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
goto onError;
interp->codec_search_path is NULL and _PyCodecRegistry_Init() returns -1.
This problems is already known; Solutions like removing python27, or setting environment variables PYTHONPATH or PYTHONHOME to either "" or the src path do not work.
I link to cpython version 3.8.0a3 which I've compiled with the included scripts inside the PCBUILD folder, using the same compiler as my applications (MSVC 15 2017).
The OS is windows 8.1 64 bit.
My application links to the produced binary python38.dll / python38.lib successfully but then crashes at runtime, and I have no idea what might cause the trouble - people suggest the environment is polluted, but it must not depend on the system's environment. How would I confidently ship the app to other people's computers? Did I maybe miss some compile flags or defines?

I'm sure you are, but you are doing this after Py_Initialize ?
I include the python3.8 dll but when starting up I take the executable full
path and then add that to the python path (the code below is not tested but
it's roughly what I do)
void py_add_to_path (const char *path)
{
PyObject *py_cur_path, *py_item;
char *new_path;
int wc_len, i;
wchar_t *wc_new_path;
char *item;
new_path = strdup(path);
py_cur_path = PySys_GetObject("path");
for (i = 0; i < PyList_Size(py_cur_path); i++) {
char *tmp = strappend(new_path, PATHSEP);
myfree(new_path);
new_path = tmp;
py_item = PyList_GetItem(py_cur_path, i);
if (!PyUnicode_Check(py_item)) {
continue;
}
item = py_obj_to_str(py_item);
if (!item) {
continue;
}
tmp = strappend(new_path, item);
free(new_path);
new_path = tmp;
free(item);
}
/* Convert to wide chars. */
wc_len = sizeof(wchar_t) * (strlen(new_path) + 1);
wc_new_path = (wchar_t *) malloc(wc_len, "wchar str");
mbstowcs(wc_new_path, new_path, wc_len);
PySys_SetPath(wc_new_path);
}

Seems a bit old now but looks like there is need to add the Lib folder including all the python system files to the search paths of the application.
Take a look at this Python port for UWP
It has an embedded python34app.zip that includes the codec files.

Related

Can I use QCommandLineParser to determine GUI mode or CLI mode?

One of the programs that I work with has two modes that it can run in: GUI (Graphical User Interface) mode or CLI (Command-Line Interface) mode. We determine which mode to use via a command line argument (i.e., if "--cli" is passed, it will use CLI mode).
The type of QApplication that is instantiated depends on which mode is used: QApplication should be used for GUI mode, and QCoreApplication should be used for CLI mode, because the GUI parts of Qt should not be instantiated for CLI mode (since CLI mode does not use or need them).
I can do that via code similar to the following:
std::unique_ptr<QCoreApplication> app =
(cliMode) ? std::make_unique<QCoreApplication>(argc, argv)
: std::make_unique<QApplication>(argc, argv);
// Do some other stuff...
return app->exec();
Since I am already using Qt, it makes sense to use QCommandLineParser to parse my arguments. After parsing the arguments, I want to analyze them to determine whether we should run in GUI mode or CLI mode. However, it has been becoming increasingly difficult to do so.
The first problem I noticed was the following on Linux (this did not happen in older versions of Qt5, but it does happen in the newer versions):
$ ./myQtApplication --help
QCoreApplication::arguments: Please instantiate the QApplication object first
Segmentation fault (core dumped)
Okay: so I can no longer run the --help command without already having a QApplication object instantiated. I temporarily fixed this by manually parsing the arguments to see whether or not --help is an argument. If it is, go ahead and instantiated the QCoreApplication, parse the arguments, and then exit.
But then I started getting a cryptic error on Mac OS X. When I would run the executable on OS X directly, it would run without any issues. But if I tried to double-click on the .app file or type in the terminal $ open myQtApplication.app, I would get this cryptic error:
LSOpenURLsWithRole() failed with error -10810 for the file ./myQtApplication.app
Since it is a rather cryptic error, it took me a long time to figure out that this error was being caused by the QCommandLineParser being used before having a QApplication object instantiated.
To fix this, I am now doing the following:
Manually parse the arguments at the beginning of the main() function to determine whether or not --cli was passed.
Instantiate a QApplication object based on the results of #1.
Run QCommandLineParser to process the rest of the arguments.
This is not a very clean way to do this because I now have two argument parsers: one to determine if --cli was passed, and the rest for the other arguments.
Is there a much better, or "proper", way to do this?
I guess the main question is: can I use QCommandLineParser to determine whether to instantiate a QCoreApplication object or a QApplication object?
Of course you can use the parser - as long as QCoreApplication already present. If the --cli option is absent, you will switch to a QApplication. Recall that you have full control over the lifetime of the application object.
This works under Qt 4.8 and 5.11 on both Windows and OS X:
// https://github.com/KubaO/stackoverflown/tree/master/questions/app-cli-gui-switch-52649458
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtWidgets>
#endif
struct Options {
bool cli;
};
static Options parseOptionsQt4() {
Options opts = {};
for (auto arg : QCoreApplication::arguments().mid(1)) {
if (arg == "--cli")
opts.cli = true;
else
qFatal("Unknown option %s", arg.toLocal8Bit().constData());
}
return opts;
}
static Options parseOptions() {
if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) return parseOptionsQt4();
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
Options opts = {};
QCommandLineParser parser;
QCommandLineOption cliOption("cli", "Start in command line mode.");
parser.addOption(cliOption);
parser.process(*qApp);
opts.cli = parser.isSet(cliOption);
return opts;
#endif
}
int main(int argc, char *argv[]) {
QScopedPointer<QCoreApplication> app(new QCoreApplication(argc, argv));
auto options = parseOptions();
if (options.cli) {
qDebug() << "cli";
} else {
qDebug() << "gui";
app.reset();
app.reset(new QApplication(argc, argv));
}
if (qobject_cast<QApplication *>(qApp))
QMessageBox::information(nullptr, "Hello", "Hello, World!");
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
return app->exec();
}

Allocating memory in Flash for user data (STM32F4 HAL)

I'm trying to use the internal flash of an STM32F405 to store a bunch of user settable bytes that remain after rebooting.
I'm using:
uint8_t userConfig[64] __attribute__((at(0x0800C000)));
to allocate memory for the data I want to store.
When the program starts, I check to see if the first byte is set to 0x42, if not, i set it using:
HAL_FLASH_Unlock();
HAL_FLASH_Program(TYPEPROGRAM_BYTE, &userConfig[0], 0x42);
HAL_FLASH_Lock();
After that I check the value in userConfig[0] and I see 0x42... Great!
When I hit reset, however, and look at the location again, it's not 0x42 anymore...
Any idea where I'm going wrong? I've also tried:
#pragma location = 0x0800C00
volatile const uint8_t userConfig[64]
but I get the same result..
Okay I found an answer on the ST forums thanks to clive1. This example works for an STM32F405xG.
First we need to modify the memory layout in the linker script file (.ld file)
Modify the existing FLASH and add a new line for DATA. Here I've allocated all of section 11.
MEMORY
{
FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 1M-128K
DATA (RWX) : ORIGIN = 0x080E0000, LENGTH = 128k
...
...
}
Manual for editing linker files on the sourceware website
In the same file, we need to add:
.user_data :
{
. = ALIGN(4);
*(.user_data)
. = ALIGN(4);
} > DATA
This creates a section called .user_data that we can address in the program code.
Finally, in your .c file add:
__attribute__((__section__(".user_data"))) const uint8_t userConfig[64]
This specifies that we wish to store the userConfig variable in the .user_data section and const makes sure the address of userConfig is kept static.
Now, to write to this area of flash during runtime, you can use the stm32f4 stdlib or HAL flash driver.
Before you can write to the flash, it has to be erased (all bytes set to 0xFF) The instructions for the HAL library say nothing about doing this for some reason...
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR );
FLASH_Erase_Sector(FLASH_SECTOR_11, VOLTAGE_RANGE_3);
HAL_FLASH_Program(TYPEPROGRAM_WORD, &userConfig[index], someData);
HAL_FLASH_Lock();

redefine \nomencl_command in LyX

I am trying to redefine the \nomencl_command in LyX, in order to be able to use the glossaries package in stead of the obsolete nomencl.
LyX allows you to specify the Nomenclature command, which by default is set to:
makeindex -s nomencl.ist
For glossaries the command is thus changed to:
makeglossaries
However, the LyX implementation of nomencl uses the more recent .nlo as an input file, and the .nls as an output file. Whereas glossaries uses the 'older' .glo and .gls Unfortunately, the extensions cannot be specified.
I found that the preferences file only says:
\nomencl_command "makeglossaries"
but the log output says:
makeglossaries "[filename].nlo" -o [filename].nls
So my question is where is \nomencl_command defined further?
The relevant code is in src/LaTeX.cpp.
Note below that some diagnostic information is written to the latex debug flag. You can see this info on the terminal if you run LyX with lyx -dbg latex.
The following are excerpts from the file src/LaTeX.cpp from the soon-to-be-released (a matter of days) LyX 2.1.
FileName const nlofile(changeExtension(file.absFileName(), ".nlo"));
// If all nomencl entries are removed, nomencl writes an empty nlo file.
// DepTable::hasChanged() returns false in this case, since it does not
// distinguish empty files from non-existing files. This is why we need
// the extra checks here (to trigger a rerun). Cf. discussions in #8905.
// FIXME: Sort out the real problem in DepTable.
if (head.haschanged(nlofile) || (nlofile.exists() && nlofile.isFileEmpty()))
rerun |= runMakeIndexNomencl(file, ".nlo", ".nls");
FileName const glofile(changeExtension(file.absFileName(), ".glo"));
if (head.haschanged(glofile))
rerun |= runMakeIndexNomencl(file, ".glo", ".gls");
and
bool LaTeX::runMakeIndexNomencl(FileName const & file,
string const & nlo, string const & nls)
{
LYXERR(Debug::LATEX, "Running MakeIndex for nomencl.");
message(_("Running MakeIndex for nomencl."));
string tmp = lyxrc.nomencl_command + ' ';
// onlyFileName() is needed for cygwin
tmp += quoteName(onlyFileName(changeExtension(file.absFileName(), nlo)));
tmp += " -o "
+ onlyFileName(changeExtension(file.toFilesystemEncoding(), nls));
Systemcall one;
one.startscript(Systemcall::Wait, tmp, path);
return true;
}
and
// nomencl file
FileName const nls(changeExtension(file.absFileName(), ".nls"));
nls.removeFile();
// nomencl file (old version of the package)
FileName const gls(changeExtension(file.absFileName(), ".gls"));
gls.removeFile();

Qt 4.7.4: Is there a way to find out the status of CAPS LOCK?

I know there were earlier problems with this in < 4.7.4 Qt versions. has this been resolved?
I don't know any Qt solution.
However this code should work on both windows (not tested) and x11-based os (works on linux)
#include <X11/XKBlib.h>
#include <QX11Info>
bool capsOn()
{
#ifdef Q_WS_WIN // MS Windows version
return GetKeyState(VK_CAPITAL) == 1;
#elif Q_WS_X11 // X11 version
unsigned int n = 0;
Display *d = QX11Info::display();
XkbGetIndicatorState(d, XkbUseCoreKbd, &n);
return (n & 0x01) == 1;
#else
# error Platform not supported
#endif
}
On X11 don't forget to add -lX11 to LIBS in your qmake project file.
I don't exactly know how to do this on OS X. If you need it, take a look at IOHIKeyboard and its's alphaLock() function. Also check this, especially the function darwinQueryHIDModifiers.

Cross platform way of testing whether a file is a directory

Currently I have some code like (condensed and removed a bunch of error checking):
dp = readdir(dir);
if (dp->d_type == DT_DIR) {
}
This works swimmingly on my Linux machine. However on another machine (looks like SunOS, sparc):
SunOS HOST 5.10 Generic_127127-11 sun4u sparc SUNW,Ultra-5_10
I get the following error at compile time:
error: structure has no member named `d_type'
error: `DT_DIR' undeclared (first use in this function)
I thought the dirent.h header was crossplatform (for POSIX machines). Any suggestions.
Ref http://www.nexenta.org/os/Porting_Codefixes:
The struct dirent definition in solaris does not contain the d_type field. You would need to make the changes as follows
if (de->d_type == DT_DIR)
{
return 0;
}
changes to
struct stat s; /*include sys/stat.h if necessary */
..
..
stat(de->d_name, &s);
if (s.st_mode & S_IFDIR)
{
return 0;
}
Since stat is also POSIX standard it should be more cross-platform. But you may want to use if ((s.st_mode & S_IFMT) == S_IFDIR) to follow the standard.

Resources