I would like to add code to the SWIG generated wrappers in cpp wrap file. For example adding global mutex to prevent C# garbage collector from changing some shared variable.
SWIGEXPORT int SWIGSTDCALL CSharp_swig_generated_method___(void *jarg1) {
int jresult; //SWIG generated
// inject code here like mutex begin
/*
SWIG generated code
*/
jresult = result;
// inject code here like mutex end
return jresult;
}
I have tried %exception directive
%exception %{
MUTEX_BEGIN
$action
MUTEX_END
%}
But this only puts the actual method call between the mutex statements. I would also like to put the additional SWIG generated code like creating a result variable, assigning jresult etc. between the mutex statements as well. Only the declaration of jresult and the return statement needs to be outside the mutex calls.
A rather painful exploration of SWIG's entire documentation, will easily reveal that SWIG was never designed with the ability of grouping the following 3 sub-stages of its processing, into one, logical, and customizable in the same time, group:
Also, SWIG's support for setting some "use always single threading" context is missing completely. It just ... doesn't seem to care, and puts the burden to the developer / SWIG user.
While SWIG's support for other target languages than C#, Pyton for example, seems to feature stronger semantics for customizations involving the ability to add a developer-defined "prologue" and "epilogue" code. For example, search in the SWIG's official docs for keywords such as:
%pythonprepend,%pythonappend, and%feature("action").That being said, there is apparently a rather obscure SWIG feature which could be employed to solve the problem that is being asked. It is the
modifiersoptional part of SWIG's%typemap%syntax. Which can be better described as "Typemaps Parameterized by Optional Temporary / Local Variables".This and a bit weird SWIG syntactic construct is first mentioned in some obscure, old entry in the SWIG's general CHANGELOG. A search for
Added a local variable extension to the typemap handlerin that change log will yield a log entry dated 5/4/97 and mentioning something like: "This mechanism [...] also makes it possible to write thread-safe typemaps."This is a rather important finding, which the leads us to this reference in SWIG's official documentation (for version 4.1): https://www.swig.org/Doc4.1/SWIGDocumentation.html#Typemaps_defining
We can thus employ this "Typemaps Parameterized by Optional Temporary / Local Variables" feature for a
%typemap(out)definition, like this:... where
CUSTOM_RAII_MACRO_BEGINandCUSTOM_RAII_MACRO_ENDdenote two C pre-processor macro definitions, to designate RAII / aquiring access to some synchronization primitive such as a mutex, for serializing access in a thread-safe way, and leaving/releasing such primitive, respectively.... and
CUSTOM_RAII_MACRO_CTXis just a third, dummy, empty C pre-processor macro definition, defined for example like this:The
CUSTOM_RAII_MACRO_CTXis defined only for the purpose of tricking SWIG into thinking that it denotes thenameof a temporary, local variable, for SWIG to generate using a standard C/C++typename varNamedeclaration statement. You see what we did here?I've applied the idea stated above, pragmatically, in a project and for the use case exactly mentioned in the original question. The part of the work that is the most involving consists of:
%typemap(out)definitions that it may have currently, by writing:Making sure to add output "Typemaps Parameterized by Optional Temporary / Local Variables" definition overrides for all of the built-in C++ types. Suggested list of types to override:
bool,char,signed char,unsigned char,short,unsigned short,int,unsigned int,long,long long,unsigned long long,float,double,ULONG,DWORD.Add similar overrides for App Domain-specific, user-defined types that are simple aliases to built-in C++ types, and of non-pointer and non-reference kind. Example:
time_tin the land of standard C library. OrHRESULTfor Windows-based programming.Add overrides for the reference (i.e.
typename&) flavor of all the types overridden in Step 2 and 3.Add these special types after the two groups of output type overrides shown above:
filename.iinterface definition files who might introduce their own%typemap(out)customized directives, and which may intersect / get in conflict with the type overrides suggested above. The SWIG#includeand%includeinclusion order is very important in this context.Hope this helps.