Skip to content

Instantly share code, notes, and snippets.

@vadz
Last active March 4, 2019 13:47
Show Gist options
  • Save vadz/c6a9cf0c62d8db7ad687992735a9ae08 to your computer and use it in GitHub Desktop.
Save vadz/c6a9cf0c62d8db7ad687992735a9ae08 to your computer and use it in GitHub Desktop.
C# typemaps for OptionalValue
// The macro arguments for all these macros are the name of the exported class
// and the C++ type T of OptionalValue<T> to generate the typemaps for.
// Common part of the macros below, shouldn't be used directly.
%define DEFINE_OPTIONAL_HELPER(OptT, T)
// The OptionalValue<> specializations themselves are only going to be used
// inside our own code, the user will deal with either T? or T, depending on
// whether T is a value or a reference type, so make them private to our own
// assembly.
%typemap(csclassmodifiers) OptionalValue< T > "internal class"
// Do this to use reference typemaps instead of the pointer ones used by
// default for the member variables of this type.
//
// Notice that this must be done before %template below, SWIG must know about
// all features attached to the type before dealing with it.
%naturalvar OptionalValue< T >;
// Even although we're not going to really use them, we must still name the
// exported template instantiation, otherwise SWIG would give it an
// auto-generated name starting with SWIGTYPE which would be even uglier.
%template(OptT) OptionalValue< T >;
%enddef
// This macro should be used for simple types that can be represented as
// Nullable<T> in C#.
//
// It exists in 2 versions: normal one for native C# code and special dumbed
// down version used for COM clients such as VBA.
#ifndef USE_OBJECT_FOR_SIMPLE_OPTIONAL_VALUES
%define DEFINE_OPTIONAL_SIMPLE(OptT, T)
DEFINE_OPTIONAL_HELPER(OptT, T)
// Define the type we want to use in C#.
%typemap(cstype) OptionalValue< T >, const OptionalValue< T > & "$typemap(cstype, T)?"
// This typemap is used to convert C# OptT to the handler passed to the
// intermediate native wrapper function. Notice that it assumes that the OptT
// variable is obtained from the C# variable by prefixing it with "opt", this
// is important for the csvarin typemap below which uses "optvalue" because the
// property value is accessible as "value" in C#.
%typemap(csin,
pre=" OptT opt$csinput = $csinput.HasValue ? new OptT($csinput.Value) : new OptT();"
) const OptionalValue< T >& "$csclassname.getCPtr(opt$csinput)"
// This is used for functions returning optional values.
%typemap(csout, excode=SWIGEXCODE) OptionalValue< T >, const OptionalValue< T >& {
OptT optvalue = new OptT($imcall, $owner);$excode
if (optvalue.IsValid())
return optvalue.Get();
else
return null;
}
// This code is used for the optional-valued properties in C#.
%typemap(csvarin, excode=SWIGEXCODE2) const OptionalValue< T >& %{
set {
OptT optvalue = value.HasValue ? new OptT(value.Value) : new OptT();
$imcall;$excode
}%}
%typemap(csvarout, excode=SWIGEXCODE2) const OptionalValue< T >& %{
get {
OptT optvalue = new OptT($imcall, $owner);$excode
if (optvalue.IsValid())
return optvalue.Get();
else
return null;
}%}
%enddef
#else // COM version of the macro
%define DEFINE_OPTIONAL_SIMPLE(OptT, T)
DEFINE_OPTIONAL_HELPER(OptT, T)
%typemap(cstype) OptionalValue< T >, const OptionalValue< T > & "object"
// Note: the test for the input value being empty (in the sense of VT_EMPTY) is
// done using ToString() because checking "is $typemap(cstype, T)" doesn't work
// for enum types and there doesn't seem to be any other way to generically
// check if the input argument contains a value or not.
%typemap(csin,
pre=" OptT opt$csinput = $csinput.ToString().Length > 0 ? new OptT(($typemap(cstype, T))$csinput) : new OptT();"
) const OptionalValue< T >& "$csclassname.getCPtr(opt$csinput)"
%typemap(csout, excode=SWIGEXCODE) OptionalValue< T >, const OptionalValue< T >& {
OptT optvalue = new OptT($imcall, $owner);$excode
if (optvalue.IsValid())
return optvalue.Get();
else
return null;
}
// No need to define csvar{in,out} as we don't use properties for
// optional-valued values anyhow because VBA doesn't handle them neither.
%enddef
#endif // normal/COM versions of DEFINE_OPTIONAL_SIMPLE
%define DEFINE_OPTIONAL_CLASS_HELPER(OptT, T)
DEFINE_OPTIONAL_HELPER(OptT, T)
%typemap(cstype) const OptionalValue< T > & "$typemap(cstype, T)"
%typemap(csin,
pre=" OptT opt$csinput = $csinput != null ? new OptT($csinput): new OptT();"
) const OptionalValue< T >& "$csclassname.getCPtr(opt$csinput)"
%typemap(csvarin, excode=SWIGEXCODE2) const OptionalValue< T >& %{
set {
OptT optvalue = value != null ? new OptT(value) : new OptT();
$imcall;$excode
}%}
%typemap(csvarout, excode=SWIGEXCODE2) const OptionalValue< T >& %{
get {
OptT optvalue = new OptT($imcall, $owner);$excode
return optvalue.IsValid() ? optvalue.Get() : null;
}%}
%enddef
// This macro should be used for optional classes which are represented by
// either a valid object or null in C#.
//
// Its arguments are the scope in which the class is defined (either a
// namespace or, possibly, a class name if this is a nested class) and the
// unqualified name of the class, the name of the exported optional type is
// constructed by prepending "Optional" to the second argument.
%define DEFINE_OPTIONAL_CLASS(scope, classname)
DEFINE_OPTIONAL_CLASS_HELPER(Optional ## classname, scope::classname)
%enddef
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment