Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/ObjCRuntime/DynamicRegistrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,11 @@ protected override bool IsAbstract (Type type)
return type.IsAbstract;
}

protected override bool IsPointer (Type type)
{
return type.IsPointer;
}

protected override bool IsINativeObject (Type type)
{
return typeof (INativeObject).IsAssignableFrom (type);
Expand Down
4 changes: 4 additions & 0 deletions src/ObjCRuntime/Registrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ protected virtual void OnRegisterCategory (ObjCType type, ref List<Exception> ex
protected abstract bool IsGenericMethod (TMethod method);
protected abstract bool IsInterface (TType type);
protected abstract bool IsAbstract (TType type);
protected abstract bool IsPointer (TType type);
protected abstract TType GetGenericTypeDefinition (TType type);
protected abstract bool VerifyIsConstrainedToNSObject (TType type, out TType constrained_type);
protected abstract TType GetEnumUnderlyingType (TType type);
Expand Down Expand Up @@ -2715,6 +2716,9 @@ protected string ToSignature (TType type, ObjCMember member, ref bool success, b
return "@"; // But we don't care about the actual type, we'll just return '@'. We only support NSArrays of the element type, so '@' is always right.
}

if (IsPointer (type))
return "^" + ToSignature (GetElementType (type), member, ref success);

success = false;
return string.Empty;
}
Expand Down
20 changes: 18 additions & 2 deletions src/bgen/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,13 @@ string ParameterGetMarshalType (MarshalInfo mai, bool formatted = false)
return (mai.IsOut ? "out " : "ref ") + (formatted ? FormatType (null, elementType) : elementType.Name);
}

// Pass "ValueType*" directly
if (mai.Type.IsPointer) {
var elementType = mai.Type.GetElementType ();
if (elementType.IsValueType)
return (formatted ? FormatType (null, elementType) : elementType.Name) + "*";
}

if (mai.Type.IsSubclassOf (TypeManager.System_Delegate)) {
return NativeHandleType;
}
Expand Down Expand Up @@ -968,6 +975,13 @@ public string MarshalParameter (MethodInfo mi, ParameterInfo pi, bool null_allow
return (pi.IsOut ? "out " : "ref ") + safe_name;
}

// Handle 'ValueType* foo'
if (pi.ParameterType.IsPointer) {
var et = pi.ParameterType.GetElementType ();
if (et.IsValueType)
return safe_name;
}

if (pi.ParameterType.IsSubclassOf (TypeManager.System_Delegate)) {
return String.Format ("(IntPtr) block_ptr_{0}", pi.Name);
}
Expand Down Expand Up @@ -1077,7 +1091,7 @@ string MakeSig (string send, bool stret, MethodInfo mi, bool aligned)
continue;
sb.Append ("_");
try {
sb.Append (ParameterGetMarshalType (new MarshalInfo (this, mi, pi)).Replace (' ', '_'));
sb.Append (ParameterGetMarshalType (new MarshalInfo (this, mi, pi)).Replace (' ', '_').Replace ('*', '_'));
} catch (BindingException ex) {
throw new BindingException (1079, ex.Error, ex, ex.Message, pi.Name.GetSafeParamName (), mi.DeclaringType, mi.Name);
}
Expand Down Expand Up @@ -1145,7 +1159,7 @@ void RegisterMethod (bool need_stret, MethodInfo mi, string method_name, bool al
else if (returnType == "char")
print (m, "\t\t[return: MarshalAs (UnmanagedType.U2)]");

print (m, "\t\tpublic extern static {0} {1} ({3}IntPtr receiver, IntPtr selector{2});",
print (m, "\t\tpublic unsafe extern static {0} {1} ({3}IntPtr receiver, IntPtr selector{2});",
returnType, method_name, b.ToString (),
need_stret ? (aligned ? "IntPtr" : "out " + FormatTypeUsedIn ("ObjCRuntime", mi.ReturnType)) + " retval, " : "");
}
Expand Down Expand Up @@ -3703,6 +3717,8 @@ void GenerateTypeLowering (MethodInfo mi, bool null_allowed_override, out String
// convs.AppendFormat ("{0}.Handle", pi.Name.GetSafeParamName ());
} else if (HasBindAsAttribute (pi)) {
convs.AppendFormat ("var nsb_{0} = {1}\n", pi.Name, GetToBindAsWrapper (mi, null, pi));
} else if (mai.Type.IsPointer && mai.Type.GetElementType ().IsValueType) {
// nothing to do
} else {
if (mai.Type.IsClass && !mai.Type.IsByRef &&
(mai.Type != TypeManager.Selector && mai.Type != TypeManager.Class && mai.Type != TypeManager.System_String && !TypeManager.INativeObject.IsAssignableFrom (mai.Type)))
Expand Down
4 changes: 2 additions & 2 deletions tests/generator/tests/ref-out-parameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ interface RefOutParameters {
[Export ("testString:a:b:")]
void TestString (int action, ref string refValue, out string outValue);

[Export ("testInt:a:b:")]
void TestInt (int action, ref int refValue, out int outValue);
[Export ("testInt:a:b:c:")]
unsafe void TestInt (int action, ref int refValue, out int outValue, int* ptrValue);

[Export ("testSelector:a:b:")]
void TestSelector (int action, ref Selector refValue, out Selector outValue);
Expand Down
3 changes: 3 additions & 0 deletions tests/monotouch-test/ObjCRuntime/Messaging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ public struct objc_super {
[DllImport (LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
public extern static void void_objc_msgSend_int_int_int (IntPtr receiver, IntPtr selector, int p1, ref int p2, out int p3);

[DllImport (LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
public unsafe extern static void void_objc_msgSend_int_int_int_int (IntPtr receiver, IntPtr selector, int p1, ref int p2, out int p3, int* p4);

[DllImport (LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
public extern static void void_objc_msgSend_IntPtr_IntPtr_IntPtr_IntPtr_IntPtr_IntPtr_IntPtr (IntPtr receiver, IntPtr selector, ref IntPtr p1, ref IntPtr p2, ref IntPtr p3, ref IntPtr p4, ref IntPtr p5, ref IntPtr p6, ref IntPtr p7);

Expand Down
70 changes: 54 additions & 16 deletions tests/monotouch-test/ObjCRuntime/RegistrarTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3688,13 +3688,14 @@ public void RefOutTest_String ()
}

[Test]
public void RefOutTest_Int ()
public unsafe void RefOutTest_Int ()
{
using (var obj = new RefOutParametersSubclass ()) {
var sel = Selector.GetHandle ("testInt:a:b:");
var sel = Selector.GetHandle ("testInt:a:b:c:");
var dummyObj = 314;
int refObj = 0;
int outObj = 0;
int ptrObj = 0;
int action;

/// 1: set both to 0
Expand All @@ -3703,30 +3704,38 @@ public void RefOutTest_Int ()
// native
refObj = dummyObj; // set to non-null
outObj = dummyObj; // set to non-null
obj.TestInt (action << 0, ref refObj, out outObj);
ptrObj = dummyObj; // set to non-null
obj.TestInt (action << 0, ref refObj, out outObj, &ptrObj);
Assert.AreEqual (0, refObj, "Int-1A-ref");
Assert.AreEqual (0, outObj, "Int-1A-out");
Assert.AreEqual (0, ptrObj, "Int-1A-ptr");

// managed
refObj = dummyObj; // set to non-null
outObj = dummyObj; // set to non-null
obj.TestInt (action << 8, ref refObj, out outObj);
ptrObj = dummyObj; // set to non-null
obj.TestInt (action << 8, ref refObj, out outObj, &ptrObj);
Assert.AreEqual (0, refObj, "Int-1M-ref");
Assert.AreEqual (0, outObj, "Int-1M-out");
Assert.AreEqual (0, ptrObj, "Int-1M-ptr");

// direct native
refObj = dummyObj; // set to non-null
outObj = dummyObj; // set to non-null
Messaging.void_objc_msgSend_int_int_int (obj.Handle, sel, action << 0, ref refObj, out outObj);
ptrObj = dummyObj; // set to non-null
Messaging.void_objc_msgSend_int_int_int_int (obj.Handle, sel, action << 0, ref refObj, out outObj, &ptrObj);
Assert.AreEqual (0, refObj, "Int-1DA-ref");
Assert.AreEqual (0, outObj, "Int-1DA-out");
Assert.AreEqual (0, ptrObj, "Int-1DA-ptr");

// direct managed
refObj = dummyObj; // set to non-null
outObj = dummyObj; // set to non-null
Messaging.void_objc_msgSend_int_int_int (obj.Handle, sel, action << 8, ref refObj, out outObj);
ptrObj = dummyObj; // set to non-null
Messaging.void_objc_msgSend_int_int_int_int (obj.Handle, sel, action << 8, ref refObj, out outObj, &ptrObj);
Assert.AreEqual (0, refObj, "Int-1DM-ref");
Assert.AreEqual (0, outObj, "Int-1DM-out");
Assert.AreEqual (0, ptrObj, "Int-1DM-ptr");

/// 2: N/A for testInt

Expand All @@ -3736,34 +3745,46 @@ public void RefOutTest_Int ()
// native
refObj = dummyObj; // set to non-null
outObj = dummyObj; // set to non-null
obj.TestInt (action << 0, ref refObj, out outObj);
ptrObj = dummyObj; // set to non-null
obj.TestInt (action << 0, ref refObj, out outObj, &ptrObj);
Assert.AreNotEqual (dummyObj, refObj, "Int-3A-ref");
Assert.AreNotEqual (dummyObj, outObj, "Int-3A-out");
Assert.AreNotEqual (dummyObj, ptrObj, "Int-3A-ptr");
Assert.AreEqual (refObj, outObj, "Int-3A-out-ref-eq");
Assert.AreEqual (refObj, ptrObj, "Int-3A-out-ptr-eq");

// managed
refObj = dummyObj; // set to non-null
outObj = dummyObj; // set to non-null
obj.TestInt (action << 8, ref refObj, out outObj);
ptrObj = dummyObj; // set to non-null
obj.TestInt (action << 8, ref refObj, out outObj, &ptrObj);
Assert.AreNotEqual (dummyObj, refObj, "Int-3M-ref");
Assert.AreNotEqual (dummyObj, outObj, "Int-3M-out");
Assert.AreNotEqual (dummyObj, ptrObj, "Int-3M-ptr");
Assert.AreEqual (refObj, outObj, "Int-3M-out-ref-eq");
Assert.AreEqual (refObj, ptrObj, "Int-3M-out-ptr-eq");

// direct native
refObj = dummyObj; // set to non-null
outObj = dummyObj; // set to non-null
Messaging.void_objc_msgSend_int_int_int (obj.Handle, sel, action << 0, ref refObj, out outObj);
ptrObj = dummyObj; // set to non-null
Messaging.void_objc_msgSend_int_int_int_int (obj.Handle, sel, action << 0, ref refObj, out outObj, &ptrObj);
Assert.AreNotEqual (dummyObj, refObj, "Int-3DA-ref");
Assert.AreNotEqual (dummyObj, outObj, "Int-3DA-out");
Assert.AreNotEqual (dummyObj, ptrObj, "Int-3DA-ptr");
Assert.AreEqual (refObj, outObj, "Int-3DA-out-ref-same");
Assert.AreEqual (refObj, ptrObj, "Int-3DA-out-ptr-same");

// direct managed
refObj = dummyObj; // set to non-null
outObj = dummyObj; // set to non-null
Messaging.void_objc_msgSend_int_int_int (obj.Handle, sel, action << 8, ref refObj, out outObj);
ptrObj = dummyObj; // set to non-null
Messaging.void_objc_msgSend_int_int_int_int (obj.Handle, sel, action << 8, ref refObj, out outObj, &ptrObj);
Assert.AreNotEqual (dummyObj, refObj, "Int-3DM-ref");
Assert.AreNotEqual (dummyObj, outObj, "Int-3DM-out");
Assert.AreNotEqual (dummyObj, ptrObj, "Int-3DM-ptr");
Assert.AreEqual (refObj, outObj, "Int-3DM-out-ref-eq");
Assert.AreEqual (refObj, ptrObj, "Int-3DM-out-ptr-eq");


/// 4 set both parameteres to different pointers of a Int
Expand All @@ -3772,38 +3793,52 @@ public void RefOutTest_Int ()
// native
refObj = 0; // set to 0
outObj = 0; // set to 0
obj.TestInt (action << 0, ref refObj, out outObj);
ptrObj = 0; // set to 0
obj.TestInt (action << 0, ref refObj, out outObj, &ptrObj);
Assert.AreNotEqual (0, refObj, "Int-4A-ref");
Assert.AreNotEqual (0, outObj, "Int-4A-out");
Assert.AreNotEqual (0, ptrObj, "Int-4A-ptr");
Assert.AreNotEqual (refObj, outObj, "Int-4A-ref-distinct");
Assert.AreNotEqual (refObj, ptrObj, "Int-4A-ptr-distinct");

// managed
refObj = 0; // set to 0
outObj = 0; // set to 0
obj.TestInt (action << 8, ref refObj, out outObj);
ptrObj = 0; // set to 0
obj.TestInt (action << 8, ref refObj, out outObj, &ptrObj);
Assert.AreNotEqual (0, refObj, "Int-4M-ref");
Assert.AreNotEqual (0, outObj, "Int-4M-out");
Assert.AreNotEqual (0, ptrObj, "Int-4M-ptr");
Assert.AreNotEqual (refObj, outObj, "Int-4M-ref-distinct");
Assert.AreNotEqual (refObj, ptrObj, "Int-4M-ptr-distinct");

// direct native
refObj = 0; // set to 0
outObj = 0; // set to 0
Messaging.void_objc_msgSend_int_int_int (obj.Handle, sel, action << 0, ref refObj, out outObj);
ptrObj = 0; // set to 0
Messaging.void_objc_msgSend_int_int_int_int (obj.Handle, sel, action << 0, ref refObj, out outObj, &ptrObj);
Assert.AreNotEqual (0, refObj, "Int-4DA-ref");
Assert.AreNotEqual (0, outObj, "Int-4DA-out");
Assert.AreNotEqual (0, ptrObj, "Int-4DA-ptr");
Assert.AreNotEqual (refObj, outObj, "Int-4DA-ref-distinct");
Assert.AreNotEqual (refObj, ptrObj, "Int-4DA-ptr-distinct");
Assert.AreEqual (3141592, refObj, "Int-4DA-ref-value");
Assert.AreEqual (2718282, outObj, "Int-4DA-out-value");
Assert.AreEqual (5772156, ptrObj, "Int-4DA-ptr-value");

// direct managed
refObj = 0; // set to 0
outObj = 0; // set to 0
Messaging.void_objc_msgSend_int_int_int (obj.Handle, sel, action << 8, ref refObj, out outObj);
ptrObj = 0; // set to 0
Messaging.void_objc_msgSend_int_int_int_int (obj.Handle, sel, action << 8, ref refObj, out outObj, &ptrObj);
Assert.AreNotEqual (0, refObj, "Int-4DM-ref");
Assert.AreNotEqual (0, outObj, "Int-4DM-out");
Assert.AreNotEqual (0, ptrObj, "Int-4DM-ptr");
Assert.AreNotEqual (refObj, outObj, "Int-4DM-ref-distinct");
Assert.AreNotEqual (refObj, ptrObj, "Int-4DM-ptr-distinct");
Assert.AreEqual (3141592, refObj, "Int-4DM-ref-value");
Assert.AreEqual (2718282, outObj, "Int-4DM-out-value");
Assert.AreEqual (5772156, ptrObj, "Int-4DM-ptr-value");
}
}

Expand Down Expand Up @@ -5174,24 +5209,27 @@ public override void TestString (int action, ref string refValue, out string out
}
}

public override void TestInt (int action, ref int refValue, out int outValue)
public unsafe override void TestInt (int action, ref int refValue, out int outValue, int* ptrValue)
{
var managedAction = (action & 0xFF00) >> 8;
switch (managedAction) {
case 0: // call native
base.TestInt (action, ref refValue, out outValue);
base.TestInt (action, ref refValue, out outValue, ptrValue);
break;
case 1: // set both to null
refValue = 0;
outValue = 0;
*ptrValue = 0;
break;
case 3: // set both parameteres to the same value
refValue = 314159;
outValue = 314159;
*ptrValue = 314159;
break;
case 4: // set both parameteres to different values
refValue = 3141592;
outValue = 2718282;
*ptrValue = 5772156;
break;
default:
throw new NotImplementedException ();
Expand Down
2 changes: 1 addition & 1 deletion tests/test-libraries/libtest.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ typedef void (^outerBlock) (innerBlock callback);
-(void) testNSObject: (int) action a:(id *) refValue b:(id *) outValue;
-(void) testNSValue: (int) action a:(NSValue **) refValue b:(NSValue **) outValue;
-(void) testString: (int) action a:(NSString **) refValue b:(NSString **) outValue;
-(void) testInt: (int) action a:(int32_t *) refValue b:(int32_t *) outValue;
-(void) testInt: (int) action a:(int32_t *) refValue b:(int32_t *) outValue c:(int32_t *) pointerValue;
-(void) testSelector: (int) action a:(SEL *) refValue b:(SEL *) outValue;
-(void) testClass: (int) action a:(Class *) refValue b:(Class *) outValue;

Expand Down
5 changes: 4 additions & 1 deletion tests/test-libraries/libtest.m
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,7 @@ -(void) testString: (int) action a:(NSString **) refValue b:(NSString **) outVal
}
}

-(void) testInt: (int) action a:(int32_t *) refValue b:(int32_t *) outValue
-(void) testInt: (int) action a:(int32_t *) refValue b:(int32_t *) outValue c:(int32_t *) pointerValue
{
NSString *obj __attribute__((unused)) = NULL;

Expand All @@ -1076,15 +1076,18 @@ -(void) testInt: (int) action a:(int32_t *) refValue b:(int32_t *) outValue
case 1: // Set both to 0
*refValue = 0;
*outValue = 0;
*pointerValue = 0;
break;
case 3: // set both parameteres to the same value
obj = @"A constant native string";
*refValue = 314159;
*outValue = 314159;
*pointerValue = 314159;
return;
case 4: // set both parameteres to different objects
*refValue = 3141592;
*outValue = 2718282;
*pointerValue = 5772156;
break;
default:
abort ();
Expand Down
10 changes: 10 additions & 0 deletions tools/common/StaticRegistrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,11 @@ protected override bool IsAbstract (TypeReference type)
return type.Resolve ()?.IsAbstract == true;
}

protected override bool IsPointer (TypeReference type)
{
return type is PointerType;
}

protected override TypeReference [] GetInterfaces (TypeReference type)
{
var td = type.Resolve ();
Expand Down Expand Up @@ -2480,6 +2485,9 @@ string ToObjCParameterType (TypeReference type, string descriptiveMethodName, Li
return res + "*";
}

if (type is PointerType pt)
return ToObjCParameterType (pt.ElementType, descriptiveMethodName, exceptions, inMethod, delegateToBlockType) + "*";

ArrayType arrtype = type as ArrayType;
if (arrtype != null)
return "NSArray *";
Expand Down Expand Up @@ -3959,6 +3967,8 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List<Exception>
} else {
setup_call_stack.AppendLine ("arg_ptrs [{0}] = &p{0};", i);
}
} else if (type.IsPointer) {
setup_call_stack.AppendLine ("arg_ptrs [{0}] = p{0};", i);
} else if (td.BaseType.FullName == "System.MulticastDelegate") {
if (isRef) {
throw ErrorHelper.CreateError (4110, Errors.MT4110, type.FullName, descriptiveMethodName);
Expand Down