Well, yes, there is a better way!...You have to start your XS files defining the macro ... #define PERL_NO_GET_CONTEXT 1
Interesting. Tracking this through, which is no easy task, this is the path taken:
(*Perl_IStdIO_ptr(((PerlInterpreter *)Perl_get_context()))) ->pStderr((*Perl_IStdIO_ptr((( PerlInterpreter* ) Perl_get_context())) +))
Perl_get_context(void) { DWORD err = GetLastError(); void *result = TlsGetValue(PL_thr_key); SetLastError(err); return result; }
Which looks up a thread-specific dispatch table base address, indexes into it to find the function (at offset pStderr) that returns the address of the stderr FILE* struct, and then invokes it (passing the address of the dispatch table as it's only argument).
FILE* PerlStdIOStderr(struct IPerlStdIO* piPerl) { return win32_stderr(); }
Note that the second call to Perl_get_context() is wasted anyway because it is not used.
DllExport FILE * win32_stderr(void) { return (stderr); }
win32_stderr(void){ return ((&_iob[2])); }
So, all of that to get the address of the third entry of the global IO block table.
Now the questions you have to ask yourself are:
Under the influence of threads? On any platform?
By the time the dispatch table is used, we are platform specific, so why not assign the platform specific function addresses directly into the table?
Why not use the fact that on any platform, a thread context switch will save & restore the thread-specific register contents. Have a platform specific assembler hack that loads a known register with the thread-specific context address (called when a thread is spawned) and allow the OS to manage the context switching directly.
Thread context references then become a macro to indirect through that known register.
Like I say, there has to be a better way.
In reply to Re^4: Inline C: using stderr segfaults?
by BrowserUk
in thread Inline C: using stderr segfaults?
by BrowserUk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |