From: Amol777 <amo...@pr...> - 2012-05-29 06:29:23
|
Thanks David for such a wonderful information .. But i have another problem after i apply %typemap(imtype, out="CSTYPE") TYPE *, TYPE & "out CSTYPE" %typemap(cstype, out="CSTYPE") TYPE *, TYPE & "out CSTYPE" type map ,the return value in c++(i.e int*) must create another class SWIG_p_int for C Sharp but in my code it becomes only int . Like my C++ function, int* Function(int* a ,int b); C sharp function becomes , public int Function(out int a,int b); Is it right? As per my knowledge return type must be SWIG_p_int .? Thanks, Amol. David Piepgrass wrote: > >> In my c++ project most of the functions having pointers as input like >> int* , >> float * ,double * ,As CSharp doesn't support pointers and passing >> pointers to >> function in c+ means parameter must returning value in its out parameter >> . >> >> so to make pointer as out , i typecast the pointers using following code >> in my >> interface file. >> >> %define INOUT_TYPEMAP(TYPE, CTYPE, CSTYPE, TYPECHECKPRECEDENCE) >> >> %typemap(ctype) TYPE *, TYPE & "CTYPE *" >> %typemap(imtype) TYPE *, TYPE & "out CSTYPE" >> %typemap(cstype) TYPE *, TYPE & "out CSTYPE" >> %typemap(csin) TYPE *, TYPE & "out $csinput" >> %typemap(in) TYPE *, TYPE & >> %{ $1 = ($1_ltype)$input; %} >> >> %typecheck(SWIG_TYPECHECK_##TYPECHECKPRECEDENCE) TYPE *INOUT, >> TYPE &INOUT "" >> %enddef > .... >> After all this changes my pointers is now converted into out as parameter >> . >> >> But if my C++ function is like >> >> int* Function(int* a ,int b); >> >> then generated C# function will become >> >> out int Function(out int a, int b) ..............return parameter also >> becomes out >> and this is not a legal statement in c#. > > You need to use the "out" attribute of the "cstype" and "imtype" typemaps: > > %typemap(imtype, out="CSTYPE") TYPE *, TYPE & "out CSTYPE" > %typemap(cstype, out="CSTYPE") TYPE *, TYPE & "out CSTYPE" > > Also, you may find the attached document helpful. > > > > > Understanding C# custom typemaps by looking at SWIG's output > > > > Understanding C# typemaps by looking at SWIG's output > Thanks to William Fulton for answering some of the questions I > had while writing this. > I found it hard to keep track the typemaps from the manual because > there are so darn many of them. So, I've created this example to help > understand them. In my experience, a number of typemaps are required for > any nontrivial wrapper. Indeed, typemaps may be the most important > feature for any "power user". > > Note that I am not discussing all the typemaps here, only > the ones that are relevant to type conversion or marshaling. > There are lots of others! (see the manual chapter 17, "SWIG and > C#", and section 10.5, "Common typemap methods"). And > I'm not covering the varin and varout typemaps, except > to say that they are like in and out but apply to > global variables (whereas the in and out typemaps apply > to member variables.) > When SWIG creates a wrapper for a function (or property), its C++ > output is based on two things: (1) the typemaps in, out, > argout, and ctype; and (2) logic hard-coded into SWIG. > There's not much you can do about the latter, except that sometimes > there are %feature directives that affect this hard-coded > logic. For example %feature("naturalvar") has some > kind of effect (see the manual section 6.6.7 for details). SWIG's C# > output also comes from typemaps and hard-coded logic, and the > relevant typemaps are imtype, cstype, csin, > csvarin, csout, and csvarout. > The following example sets all of the typemaps I mentioned > above for two types, Foo and Foo*. Notice the comments > such as /* ctype */ and /* in */. I put those there so > you can easily see how the typemaps affect the code that SWIG > generates. Now, take a look at the sample SWIG input below. It has one > set of typemaps that apply to Foo* arguments, another that apply > to Foo (passed by value), and finally some declarations that we ask > SWIG to wrap: > %module Test > > // Typemaps for passing Foo by pointer > %typemap(in) Foo* "/* in* */ $1 = $input;" > %typemap(out, null="/* null* */ NULL") Foo* "/* out* */ $result = $1;" > %typemap(argout) Foo* "/* argout* */" > %typemap(cstype, out="/* cstype* out */ Foo") Foo* "/* cstype* */ Foo" > %typemap(imtype, out="/* imtype* out */ Foo") Foo* "/* imtype* */ Foo" > %typemap(ctype, out="/* ctype* out */ Foo*") Foo* "/* ctype* */ Foo*" > %typemap(csin) Foo* "/* csin* */ $csinput" > %typemap(csvarin, excode=SWIGEXCODE2) Foo* > %{ > set { $imcall;$excode } > %} > %typemap(csout, excode=SWIGEXCODE) Foo* > { > /* csout* */ Foo ret = $imcall;$excode > return ret; > } > %typemap(csvarout, excode=SWIGEXCODE) Foo* > %{ > get { > /* csvarout* */ Foo ret = $imcall;$excode > return ret; > } > %} > // Note: SWIGEXCODE is a macro used by many csout typemaps. Definition: > // %define SWIGEXCODE > // "\n if ($modulePINVOKE.SWIGPendingException.Pending)" > // "\n throw $modulePINVOKE.SWIGPendingException.Retrieve();" > > // Typemaps for passing Foo by value > %typemap(in) Foo "/* in */ $1 = $input;" > %typemap(out, null="/* null */ Foo()") Foo "/* out */ $result = $1;" > %typemap(argout) Foo "/* argout */" > %typemap(cstype, out="/* cstype out */ Foo") Foo "/* cstype */ Foo" > %typemap(imtype, out="/* imtype out */ Foo") Foo "/* imtype */ Foo" > %typemap(ctype, out="/* ctype out */ Foo") Foo "/* ctype */ Foo" > %typemap(csin) Foo "/* csin */ $csinput" > %typemap(csvarin, excode=SWIGEXCODE2) Foo > %{ > set { $imcall;$excode } > %} > %typemap(csout, excode=SWIGEXCODE) Foo > { > /* csout */ Foo ret = $imcall;$excode > return ret; > } > %typemap(csvarout, excode=SWIGEXCODE) Foo > %{ > get { > /* csvarout */ Foo ret = $imcall;$excode > return ret; > } > %} > > Foo* ByRefExample(Foo& foo3, Foo* foo4, const Foo* foo5); > Foo ByValExample(Foo foo1, const Foo& foo2); > struct StructWithFoo { Foo X; }; > > > > By the way, there is no "real" C++ code here. I did not > really define (in C++) a type called StructWithFoo, a type called Foo, > or a function called ByRefExample or ByValExample. We're only giving > SWIG this nonsense in order to find out what the generated code looks > like. > It's important that the typemaps appear above the function > declarations, otherwise they have no effect on the functions' > wrappers. > SWIG really doesn't care that we haven't told it what Foo > is. It just uses its default behavior for struct/class types, so if > you add a declaration like struct Foo { double a; };, you'll > find that SWIG creates a wrapper for Foo::a, new Foo() and delete > Foo(), but other than that, SWIG's output remains identical. On the > other hand, if you put typedef int Foo; at the top, > substantial changes appear in the wrappers of ByRefExample and > ByValExample. Apparently SWIG treats simple types quite differently > than structures, but at least the typemaps remain intact. (By the > way, %naturalvar has absolutely no effect on this example.) > The result consists of three parts: (1) the C++ wrapper, (2) the > C# PInvoke definition and (3) the C# wrapper. It is worth mentioning > that SWIG's C++ typemaps and its C# typemaps are completely > independent. Sometimes you need to customize both the C++ and the C#, > but if the code on one side already happens to look the way you want > it, then you only have to worry about changing the other side. > Here is the C++ wrapper: > SWIGEXPORT /* ctype* out */ Foo* SWIGSTDCALL CSharp_ByRefExample(void * > jarg1, /* ctype* */ Foo* jarg2, /* ctype* */ Foo* jarg3) { > /* ctype* out */ Foo* jresult ; > Foo *arg1 = 0 ; > Foo *arg2 = (Foo *) 0 ; > Foo *arg3 = (Foo *) 0 ; > Foo *result = 0 ; > > arg1 = (Foo *)jarg1; > if(!arg1) { > > SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, > "Foo & type is null", 0); > return /* null* */ NULL; > } > /* in* */ arg2 = jarg2; > /* in* */ arg3 = jarg3; > result = (Foo *)ByRefExample(*arg1,arg2,(Foo const *)arg3); > /* out* */ jresult = result; > /* argout* */ > /* argout* */ > return jresult; > } > > SWIGEXPORT /* ctype out */ Foo SWIGSTDCALL CSharp_ByValExample(/* ctype */ > Foo jarg1, void * jarg2) { > /* ctype out */ Foo jresult ; > Foo arg1 ; > Foo *arg2 = 0 ; > Foo result; > > /* in */ arg1 = jarg1; > arg2 = (Foo *)jarg2; > if(!arg2) { > > SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, > "Foo const & type is null", 0); > return /* null */ Foo(); > } > result = ByValExample(arg1,(Foo const &)*arg2); > /* out */ jresult = result; > /* argout */ > return jresult; > } > > SWIGEXPORT void SWIGSTDCALL CSharp_StructWithFoo_X_set(void * jarg1, /* > ctype */ Foo jarg2) { > StructWithFoo *arg1 = (StructWithFoo *) 0 ; > Foo arg2 ; > > arg1 = (StructWithFoo *)jarg1; > /* in */ arg2 = jarg2; > if (arg1) (arg1)->X = arg2; > > /* argout */ > } > > > SWIGEXPORT /* ctype out */ Foo SWIGSTDCALL CSharp_StructWithFoo_X_get(void > * jarg1) { > /* ctype out */ Foo jresult ; > StructWithFoo *arg1 = (StructWithFoo *) 0 ; > Foo result; > > arg1 = (StructWithFoo *)jarg1; > result = ((arg1)->X); > /* out */ jresult = result; > return jresult; > } > > (CSharp_new_StructWithFoo and CSharp_delete_StructWithFoo are hidden; > the typemaps do not affect them.) > Observations: > > The lines with /* in */, > /* out */, and /* > null */ come from the in > and out typemaps. The in typemap is used to convert the from > argument sent to the wrapper to a second argument that is sent to > the wrapped function; the out typemap converts the return > value of the function into the return value of the wrapper. The > optional null attribute of the out typemap controls > what is returned when the wrapper wants to throw an exception (it > doesn't really matter what is returned in that case, as long > as the code ends up syntactically valid.) > /* ctype */ and /* ctype > out */ come from the ctype typemap, which controls the > data type in the wrapper. The default for all structures is void*. > Note that the out="..." attribute can override the > type of return values; it is optional and very rarely used. > /* argout */ comes from the > rarely-needed argout typemap. It allows you to do something > after the wrapped function is called. > In CSharp_ByValExample, SWIG is > actually making a copy of the return value. There may be a > performance penalty if the structure is large or if the copy > contructor of Foo does something complicated. Unfortunately there is > no way to avoid this. > The first argument of > CSharp_ByRefExample and the second argument of CSharp_ByValExample > are declared as void*. These correspond to the arguments of type > Foo& and const Foo&. This demonstrates that the typemaps for > Foo& and const Foo& are not affected by the typemaps for Foo > or Foo*. Instead, SWIG uses its default behavior when passing by > reference, which is to cast the references between Foo& and > void*. > > > Q: can I have separate typemaps for Foo* and const Foo*? A: > Yes! typemaps for const types are considered more "specific" > so SWIG prefers to use a const typemap if one exists (see chapter > 10.) Q: what if we wanted to do a null pointer check? What if we > did NOT want to do a null reference check? A: I think the > "check" > typemap is intended to control these checks (see chapter 10, > section 10.5.6), and perhaps a SWIGTYPE& typemap could be used > to configure all reference types at once. > On the other hand, the third argument to ByRefExample() is > const Foo*, yet our Foo* typemap is still being used for this > argument. > > A SWIG_CSharpArgumentNullException > is created if an argument is null and passed by reference. However, > this check is not done for the Foo* argument. > > None of these typemaps affect the > type of the wrapper's local variables, and none of them affect the > actual function call or return statement. The way all these things > look is hard-coded in SWIG. > Names like "jarg1" and "jresult" are > vestigial: the C# version of SWIG was developed from the Java > version. > > Next up, let's look at the P/Invoke declarations, located in the > generated C# class TestPINVOKE: > [DllImport("Test", EntryPoint="CSharp_ByRefExample")] > public static extern /* imtype* out */ Foo ByRefExample(HandleRef jarg1, > /* imtype* */ Foo jarg2, /* imtype* */ Foo jarg3); > > [DllImport("Test", EntryPoint="CSharp_ByValExample")] > public static extern /* imtype out */ Foo ByValExample(/* imtype */ Foo > jarg1, HandleRef jarg2); > > [DllImport("Test", EntryPoint="CSharp_StructWithFoo_X_set")] > public static extern void StructWithFoo_X_set(HandleRef jarg1, /* imtype > */ Foo jarg2); > > [DllImport("Test", EntryPoint="CSharp_StructWithFoo_X_get")] > public static extern /* imtype out */ Foo StructWithFoo_X_get(HandleRef > jarg1); > > > Here you can see that the imtype typemap controls all the > types used in these declarations. Again you can see that the > reference arguments (Foo& and const Foo&) are not affected by > our Foo and Foo* typemaps, and just use the default > type for structs/classes, HandleRef. HandleRef is a standard > part of the .NET framework, a wrapper around IntPtr, and > IntPtr is a structure equal in size to a pointer. Note that the first > argument to StructWithFoo_X_get and StructWithFoo_X_set represents a > pointer to StructWithFoo. > Finally, let's look at the C# wrapper for these functions. Since > ByRefExample and ByValExample are not part of a struct/class, they go > in a class named after the SWIG module. Since we declared the module > as > %module Test > There will be a C# class like this: > using System; > using System.Runtime.InteropServices; > > public class Test { > public static /* cstype* out */ Foo ByRefExample(SWIGTYPE_p_Foo fooA, /* > cstype* */ Foo fooB, /* cstype* */ Foo fooC) { > /* csout* */ Foo ret = > TestPINVOKE.ByRefExample(SWIGTYPE_p_Foo.getCPtr(fooA), /* csin* */ fooB, > /* csin* */ fooC); > if (TestPINVOKE.SWIGPendingException.Pending) throw > TestPINVOKE.SWIGPendingException.Retrieve(); > return ret; > } > > public static /* cstype out */ Foo ByValExample(/* cstype */ Foo foo1, > SWIGTYPE_p_Foo foo2) { > /* csout */ Foo ret = TestPINVOKE.ByValExample(/* csin */ foo1, > SWIGTYPE_p_Foo.getCPtr(foo2)); > if (TestPINVOKE.SWIGPendingException.Pending) throw > TestPINVOKE.SWIGPendingException.Retrieve(); > return ret; > } > > } > > Observations: > > > Q: How can I make SWIG automatically generate nicer > names such as FooHandle instead of SWIGTYPE_p_Foo? A: You can't. > The pattern is hard-coded. > Q: Can I make SWIG put all the pointer wrappers > into the same file, so I don't have to update my project whenever a > pointer wrapper is added or removed? A: No, you can't. > Q: What if I don't want these wrappers? Can SWIG be > told not to wrap anything that would cause one of these wrappers to > be created? A: No, it can't. Section 10.3.3 of the manual says > "if you cleared all typemaps for SWIGTYPE, SWIG simply won't > wrap any unknown datatype (which might be useful for debugging)." > But actually, if you clear those typemaps, it is equivalent to > setting them to empty strings. SWIG will simply generate > syntactically invalid wrappers. > Q: Can I make SWIG generate simplified wrappers > like one of these? > > public struct FooHandle { > private IntPtr swigCPtr; > internal FooHandle(IntPtr cPtr) { swigCPtr = cPtr; } > internal static IntPtr getCPtr(FooHandle obj) { > return (obj == null) ? > new HandleRef(null, IntPtr.Zero) : > obj.swigCPtr; > } > } > public struct FooHandle { > internal IntPtr Ptr; > internal FooHandle(IntPtr cPtr) > { Ptr = cPtr; } > } > A: %typemap(csclassmodifiers) controls whether it is a > class or struct, while %typemap(csbody) and > %typemap(csbody_derived) control the body of base and derived > classes, respectively. You can see the defaults in csharp.swg. > These are the methods that the C# programmer will call. > > The return type and argument types > are controlled by the cstype typemap, and the optional > out="..." attribute can override the type of return > values. > The arguments that were void* in > the C-style wrappers (const Foo&/Foo& in the original > functions) are now SWIGTYPE_p_Foo in the C# code. > > Unlike the C-style wrapper, which > uses argument names like "arg1", "arg2", etc., > SWIG restores the original parameter names here. > > The three lines starting with /* > csout */ come entirely from the csout typemap. The > call to TestPINVOKE.ByXXXExample(...) is the expansion of $imcall; > the exception handling part is the expansion of $excode (and thus > SWIGEXCODE). Thus, csout gives you almost total control over > how to P/Invoke the wrapper in the C# code. > The arguments to NaviPINVOKE.ByXXXExample(...) are controlled > by the csin typemap. Thus you can use csin to convert > from C# type to the type used in the P/Invoke call. > > The variable StructWithFoo::X is mapped a C# class by the same > name: > public /* cstype */ Foo X { > set { TestPINVOKE.StructWithFoo_X_set(swigCPtr, /* csin */ value); } > > get { > /* csvarout */ Foo ret = TestPINVOKE.StructWithFoo_X_get(swigCPtr); > return ret; > } > } > > > The type SWIGTYPE_p_Foo is generated to deal with pointers (or in > this case, references) to Foo: > public class SWIGTYPE_p_Foo { > private HandleRef swigCPtr; > > internal SWIGTYPE_p_Foo(IntPtr cPtr, bool futureUse) { > swigCPtr = new HandleRef(this, cPtr); > } > > protected SWIGTYPE_p_Foo() { > swigCPtr = new HandleRef(null, IntPtr.Zero); > } > > internal static HandleRef getCPtr(SWIGTYPE_p_Foo obj) { > return (obj == null) ? new HandleRef(null, IntPtr.Zero) : > obj.swigCPtr; > } > } > > Also, SWIG will generate a SWIGTYPE_p_* wrapper to deal with unknown > types that are passed by value. To see how, feed SWIG a declaration like > Unknown UnknownUnknown(Unknown Unknown); > > Standard typemaps > SWIG has a standard library of sorts that supports various complex types > such as vector<T>, std::string, and std::wstring. For more details > on these, see their source code in Lib/csharp in the SWIG distribution. > > %include stl.i to get wrappers of a few STL things; for example > vector<T> is "made to look and feel like a typesafe C# > System.Collections.ArrayList" > %include std_string.i and %include std_wstring.i to map std::string and > std::wstring (respectively) to System.String. std_wstring.i is not in the > current version of SWIG (1.3.31) so check the subversion repository. Oh > and currently there's a bug in wstring support that truncates wide > characters to one byte (I filed a bug report). > %include typemaps.i to get support for passing arguments by reference as > ref or out arguments (I know, it's not the most descriptive filename.) By > default, the arguments must be named something like int& INOUT or int& > OUTPUT to get it to work, but really you're supposed to tell SWIG > something like this after including the file: > %apply int& INOUT { int& }; > %apply int& OUTPUT { int& result }; > Then you declare functions like void f(int& reference, int& result) to get > a ref parameter and an out parameter. > The manual (sec 33.4) indicates that "swig.swg" and "csharp.swg" (for C#) > are always implicitly included at the top of your module. Looking in those > files can give you some clues about SWIG's default behaviors. > There are many more, but they're not documented in the manual; you > actually have to look in the various .i and .swg files and hope to find > some kind of description. > > Finally, this has little to do with typemaps but if you want to map pairs > of functions like GetX and SetX to C# properties like X, you'll want to > %include attribute.i. Look in Lib/attribute.i and > Lib/typemaps/attribute.swg for documentation. > Summary > Here's what the typemaps do. > > > > Typemap example (not necessarily useful) > > > Affects > > > What is it for? > > > > > %typemap(ctype) Foo& "Foo" > > > > C-side wrapper > > > 'ctype' is used to specify the data type of arguments and > return values in the C-style wrappers. Optionally, the 'out' > attribute changes the type used in case of a return value. > > > > > %typemap(in) Foo& > %{ $1 = $input; %} > > > > C-side wrapper > > > 'in' controls the conversion from the argument passed in to the > wrapper ($input, named jarg1, jarg2, etc.) and the argument that will > be sent to your C++ > function or assigned to a member variable ($1, named arg1, arg2, etc.). > 'varin' is the equivalent typemap for global variables. > > %typemap(ctype) controls the type of $input, but you cannot control the > type of $1. > For a type called Foo, $1 always has type Foo. For Foo*, Foo&, > const Foo*, const Foo& and Foo[], the type of $1 is Foo*. > Unfortunately, since $1 is different for Foo and const Foo&, you > almost always > have to write separate typemaps for those two types (instead of just > writing %typemap(in) Foo, > const Foo& %{ ... %}) > > > > > %typemap(out, null="NULL") Foo > %{ $result = $1; %} > > > C-side wrapper > > > 'out' controls the conversion from the return value of your C++ > code to the return value of the C-style wrapper. The optional > 'null' part specifies the return value used when SWIG wants to > throw an exception without calling the wrapped function (it becomes > the value of the $null special variable inside %exception handlers). > 'varout' is the equivalent typemap for global variables. > > %typemap(ctype, out="My Return Type") controls the type of $result, but > you cannot control the type of $1. > For a type called Foo, $1 always has type Foo. For return types Foo*, > Foo&, > const Foo*, and const Foo&, the type of $1 is Foo* (SWIG uses a > cast to remove the > const qualifier, if any.) Unfortunately, since $1 is different for Foo > and const Foo&, you > almost always have to write separate typemaps for those two types > (instead of just writing %typemap(out) Foo, > const Foo& %{ ... %}) > > > > > > %typemap(argout) int& NEG > %{ $input = -$input; %} > > > > C-side wrapper > > > 'argout' specifies what to do after calling the function; it can access > $1 and $input like the 'in' typemap. > > > > > %typemap(imtype, out="IntPtr") Foo& "Foo" > > > P/Invoke declaration > > > 'imtype' is the C# type of arguments and return values of a > P/Invoke ([DllImport ...] extern ...) declaration. Optionally, the > 'out' attribute changes the type used in case of a return value. > You can also control .NET attributes applied to arguments and > return values using 'inattributes' and 'outattributes' (see sec. > 17.2 in the manual) > > > > > %typemap(cstype) Foo& "Foo" > > > C#-side wrapper > > > 'cstype' controls the C# type of arguments and return values > that are exposed to the user of the C# wrapper. Just as for > cstype, you can use 'inattributes', 'outattributes', and 'out' > attributes in this typemap. > > > > > %typemap(csin) Foo& "$csinput" > > > C#-side wrapper > > > 'csin' controls an argument of the P/Invoke call. $csinput is > the name of the argument in both the wrapper and in the original > C++ function. Typically you would use this typemap to apply a > typecast to $csinput. > > > > > %typemap(csout, excode=SWIGEXCODE) Foo& { Foo ret = > $imcall;$excode return ret; } > > > C#-side wrapper > > > 'csout' specifies the body of the C# wrapper function. $imcall > expand to the P/Invoke call, while the optional $excode attribute > expands to whatever you specify; typically it is used to translate > a request for an exception into an actual exception > (because a .NET exception can't be thrown directly from the C > wrapper). Note that you must use {...} around the code of this > typemap, not %{...%}. > > > > > %typemap(csvarin, excode=SWIGEXCODE2) wchar_t %{ set { > $imcall;$excode } %} > > > C#-side wrapper > > > 'csvarin' controls the body of the property setter that > corresponds to a C++ variable. There is little reason to change this > typemap. > > > > > %typemap(csvarout, excode=SWIGEXCODE2) wchar_t %{ > get { > char ret = $imcall;$excode > return ret; > } %} > > > C#-side wrapper > > > 'csvarout' controls the body of the property getter that > corresponds to a C++ variable. If you configure csout to use some code > "{C}", you should usually set this typemap to "get {C}" > > > > Related typemaps are completely independent of each > other. In other words, if you have defined an "in" typemap > but not an "out" typemap, the default "out" > typemap will be used. The default typemaps are defined in > Lib/swig.swg and Lib/csharp/csharp.swg in the SWIG distribution, and you > are including other typemaps whenever you include one of the *.i files > that > comes with SWIG. > There is a lot more to learn about typemaps; please see chapter 10 of > the manual ("Typemaps") for more infomation. For more > information about the C# typemaps, see chapter 17, especially section > 17.2 ("Differences to the Java module"). > If you need to apply the same typemaps to a bunch of different classes, > or if you want to encapsulate a set of typemaps into a convenient package, > then use %define to create a macro, as illustrated in the first example: > Example: C# class to C++ structure. > Let's say you want to map > struct RECT { int left, top, right, bottom; }; > to the C# class > [StructLayout(LayoutKind.Sequential)] > class Rectangle { public int Left, Top, Right, Bottom; }; > > This is a good use for a macro because we might want to do the same sort > of thing for several data structures. Here's the macro; note that C# > classes cannot be passed by value, so the typemaps below only apply to > pointers and references. Also, I think the .NET marshaller copies the > class both on input and output, so you can expect function calls involving > it will be rather slow. > > %define %cs_class(TYPE, CSTYPE) > %ignore TYPE; > %typemap(ctype) TYPE*, TYPE& %{ TYPE* %} > %typemap(in) TYPE*, TYPE& %{ $1 = $input; %} > %typemap(varin) TYPE*, TYPE& %{ $1 = $input; %} > %typemap(memberin) TYPE*, TYPE& %{ $1 = $input; %} > %typemap(out, null="NULL") TYPE*, TYPE& %{ $result = $1; %} > %typemap(imtype, out="IntPtr") TYPE*, TYPE& %{ CSTYPE %} > %typemap(cstype) TYPE*, TYPE& %{ CSTYPE %} > %typemap(csin) TYPE*, TYPE& %{ $csinput %} > %typemap(csout, excode=SWIGEXCODE) TYPE*, TYPE& { > IntPtr ptr = $imcall;$excode > CSTYPE ret = (CSTYPE)Marshal.PtrToStructure(ptr, typeof(CSTYPE)); > return ret; > } > %typemap(csvarin, excode=SWIGEXCODE2) TYPE* > %{ > set { $imcall;$excode } > %} > %typemap(csvarout, excode=SWIGEXCODE2) TYPE* > %{ > get { > IntPtr ptr = $imcall;$excode > CSTYPE ret = (CSTYPE)Marshal.PtrToStructure(ptr, typeof(CSTYPE)); > return ret; > } > %} > %enddef > > // Usage: > %cs_class(RECT, Rectangle) > > > Example: Point to Point > The following complete example will take a C++ "Point" > class and map it to the C# equivalent, System.Drawing.Point: > // ***** File: Example.i ***** > %module Example > %ignore Point; > %typemap(in) Point %{ $1 = $input; %} > %typemap(out, null="Point()") Point %{ $result = $1; %} > %typemap(cstype) Point "System.Drawing.Point" > %typemap(imtype) Point "System.Drawing.Point" > %typemap(ctype) Point "Point" > %typemap(csout, excode=SWIGEXCODE) Point { > System.Drawing.Point ret = $imcall;$excode > return ret; > } > %typemap(csin) Point "$csinput" > > %inline > %{ > typedef struct { > Point(int x, int y) { this->x = x; this->y = y; } > int x,y; > } Point; > > Point CreatePoint(int x, int y) > { > Point p(x,y); > return p; > } > %} > > // ***** File: Program.cs ***** > using System.Diagnostics; > > static class Program > { > public static void Main() > { > System.Drawing.Point p = Example.CreatePoint(2, 3); > Console.WriteLine("Point: {0}, {1}", p.X, p.Y); > } > } > Example: COLORREF to Color > The following example will take a Win32 COLORREF (an alias for unsigned > long that represents a color) and map it to the C# equivalent, > System.Drawing.Color. This presents some difficulty because the two > datatypes are represented differently: COLORREF arranges the color > components R G B and A (red green blue and alpha) in the format 0x00RRGGBB > or 0xAARRGGBB, whereas Color.ToArgb() uses 0xAABBGGRR. > Ref/out arguments are supported but passed as "int" on the C# side, > because I don't think System.Drawing.Color can be marshaled by reference > directly, as SWIG doesn't provide equivalents to the "in" and "argout" > typemaps on the C# side. So Color can be converted to int, but we can't > pass it by reference. > > typedef unsigned long DWORD; > typedef DWORD COLORREF; > > // Typemaps for COLORREF <=> Color. > %{ > #define FLIP_COLOR(c) (((c >> 16) & 0xFF) | ((c & 0xFF) << 16) | (c > & 0xFF00FF00)) > %} > %typemap(ctype) COLORREF %{ COLORREF %} > %typemap(ctype, out="COLORREF") COLORREF& %{ COLORREF& %} > %typemap(in) COLORREF %{ $1 = > FLIP_COLOR($input); %} > %typemap(varin) COLORREF %{ $1 = > FLIP_COLOR($input); %} > %typemap(memberin) COLORREF %{ $1 = > FLIP_COLOR($input); %} > %typemap(in) COLORREF& %{ $input = > FLIP_COLOR($input); $1 = &$input; %} > %typemap(varin) COLORREF& %{ $input = > FLIP_COLOR($input); $1 = &$input; %} > %typemap(memberin) COLORREF& %{ $input = > FLIP_COLOR($input); $1 = &$input; %} > %typemap(argout) COLORREF& %{ $input = > FLIP_COLOR($input); %} > %typemap(out, null="0") COLORREF, COLORREF& %{ $result = > FLIP_COLOR($1); %} > %typemap(imtype) COLORREF %{ int %} > %typemap(imtype, out="int") COLORREF& %{ ref int %} > %typemap(imtype) COLORREF& OUTPUT %{ out int %} > %typemap(cstype) COLORREF %{ > System.Drawing.Color %} > %typemap(cstype, out="System.Drawing.Color") COLORREF& %{ ref int %} > %typemap(cstype) COLORREF& OUTPUT %{ out int %} > %typemap(csin) COLORREF %{ > $csinput.ToArgb() %} > %typemap(csin) COLORREF& %{ ref $csinput %} > %typemap(csin) COLORREF& OUTPUT %{ out $csinput %} > %typemap(csout, excode=SWIGEXCODE) COLORREF, COLORREF& { > System.Drawing.Color ret = System.Drawing.Color.FromArgb($imcall);$excode > return ret; > } > %typemap(csvarout, excode=SWIGEXCODE2) COLORREF, COLORREF& > %{ > get { > System.Drawing.Color ret = > System.Drawing.Color.FromArgb($imcall);$excode > return ret; > } > %} > > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Swig-user mailing list > Swi...@li... > https://lists.sourceforge.net/lists/listinfo/swig-user > > -- View this message in context: http://old.nabble.com/how-to-type-cast-pointers-for-CSharp-using-SWIG--tp33907257p33923292.html Sent from the swig-user mailing list archive at Nabble.com. |