OCC Draw在启动时可以按需加载需要的命令,不过大部分情况下我是直接执行pload ALL加载所有模块,简单粗暴。但每次都执行感觉很烦,所以直接修改其源码,让其启动时自动执行pload ALL
一、Draw运行流程
Draw在运行时是两个线程协同配合完成的,一个负责命令的执行,一个负责处理用户的输入,将输入变成命令,交给执行线程处理。两个线程的通信也很简单直接,通过读写两个字段实现的:console_command、console_semaphore。
处理用户输入线程代码是src\Draw\Draw_Window.cxx文件中的readStdinThreadFunc函数。其核心逻辑如下:
for (;;)
{
while (console_semaphore != WAIT_CONSOLE_COMMAND)
{
Sleep(100);
}
const HANDLE anStdIn = ::GetStdHandle(STD_INPUT_HANDLE);
if (anStdIn != NULL
&& anStdIn != INVALID_HANDLE_VALUE
&& isConsoleInput)
{
DWORD aNbRead = 0;
if (ReadConsoleW(anStdIn, console_command, DRAW_COMMAND_SIZE, &aNbRead, NULL))
{
console_command[aNbRead] = L'\0';
console_semaphore = HAS_CONSOLE_COMMAND;
continue;
}
else
{
const DWORD anErr = GetLastError();
if (anErr != ERROR_SUCCESS)
{
// fallback using fgetws() which would work with pipes
// but supports Unicode only through multi-byte encoding (which is not UTF-8)
isConsoleInput = false;
continue;
}
}
}
// fgetws() works only for characters within active locale (see setlocale())
if (fgetws(console_command, DRAW_COMMAND_SIZE, stdin))
{
console_semaphore = HAS_CONSOLE_COMMAND;
}
}
其原理是定期读取用户输入,如果读到数据就写入console_command,并将console_semaphore标记成HAS_CONSOLE_COMMAND。
二、让Draw自动执行pload ALL
明白其运行流程,那么自动执行pload ALL就简单了。在用户输入线程进入死循环之前,将pload命令写到console_command中就可以了。
const char * ploadCmd = "pload ALL";
for (int i = 0; i < 9; i++) {
console_command[i] = ploadCmd[i];
}
console_command[9] = L'\0';
console_semaphore = HAS_CONSOLE_COMMAND;
for (;;)
{
while (console_semaphore != WAIT_CONSOLE_COMMAND)
{
Sleep(100);
}
... 省略代码
}