Ich möchte untersuchen, wie iOS-Bibliothek mit der Verarbeitung Zeiger auf Xamarin.iOS binden. Es muss Marshalling.Wie bindet man Xamarin iOS Obj-C-Bibliothek mit Marshalling
ich eine solche Bibliothek für den Test vorbereiten,
MarshalTest.h
typedef struct
{
float x,y,z;
} Marshal3D;
@interface MarshalTest : NSObject
-(id)initWithMarshal:(Marshal3D *)marshal;
-(id)initWithMarshals:(Marshal3D *)marshals num:(int)numCoord;
-(void)addMarshal:(Marshal3D *)marshal;
-(void)addMarshals:(Marshal3D *)marshals num:(int)numCoord;
-(int)getMarshals:(Marshal3D **)getMarshals;
-(int) storedNumber;
-(float)checkMarshalValue:(int)index xyz:(int)xyz;
@end
und bereiten Binding C# Codes wie folgt aus:
StructsAndEnums.cs
using System;
using System.Runtime.InteropServices;
namespace MarshalTestNet
{
[StructLayout(LayoutKind.Sequential)]
public struct Marshal3D
{
public float x;
public float y;
public float z;
};
}
ApiDefinition.cs
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using MonoTouch.ObjCRuntime;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace MarshalTestNet
{
[BaseType (typeof (NSObject))]
public partial interface MarshalTest {
[Export ("initWithMarshal:")]
IntPtr Constructor ([In, MarshalAs(UnmanagedType.LPStruct)]Marshal3D marshal);
[Export ("initWithMarshals:num:")]
IntPtr Constructor ([In, MarshalAs(UnmanagedType.LPStruct)]Marshal3D marshals, int numCoord);
[Export ("addMarshal:")]
void AddMarshal ([In, MarshalAs(UnmanagedType.LPStruct)]Marshal3D marshal);
[Export ("addMarshals:num:")]
void AddMarshals ([In, MarshalAs(UnmanagedType.LPStruct)]Marshal3D marshals, int numCoord);
[Export ("getMarshals:")]
int GetMarshals ([Out, MarshalAs(UnmanagedType.LPStruct)]Marshal3D getMarshals);
[Export ("storedNumber")]//, Verify ("ObjC method massaged into getter property", "/Users/kokogiko/Desktop/MarshalTest.h", Line = 32)]
int StoredNumber { get; }
[Export ("checkMarshalValue:xyz:")]
float CheckMarshalValue (int index, int xyz);
}
}
Aber das funktioniert nicht, nur
wird Nachricht ohne Fehler zeigtvar mars3 = new Marshal3D{
x = 1.0f,
y = 2.0f,
z = 3.0f
};
var mars = new MarshalTest (mars3);
Aufruf beendet.
Wie binden iOS-Bibliothek mit Marshalling? Es gibt nur sehr weniger Informationen, dies zu tun ...
[Bearbeiten nach Rolf Antwort]
Danke Rolf, ich viele Fälle so leid für die Beantwortung so spät getestet.
1.
[Export ("initWithMarshal:")]
IntPtr Constructor (ref Marshal3D marshal);
[Export ("addMarshal:")]
void AddMarshal (ref Marshal3D marshal);
sehr gut funktioniert. Vielen Dank!
2.
[Export ("initWithMarshals:num:")]
IntPtr Constructor (Marshal3D[] marshals, int numCoord);
[Export ("addMarshals:num:")]
void AddMarshals (Marshal3D[] marshals, int numCoord);
nicht funktioniert, mit diesen Fehler in der Kompilierung Stufe zeigt:
obj/Debug/ios/MarshalTestNet/MarshalTest.g.cs(140,31): error CS1502: The best overloaded method match for `MonoTouch.Foundation.NSArray.FromNSObjects(params MonoTouch.Foundation.NSObject[])' has some invalid arguments
/Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll (Location of the symbol related to previous error)
obj/Debug/ios/MarshalTestNet/MarshalTest.g.cs(140,46): error CS1503: Argument `#1' cannot convert `MarshalTestNet.Marshal3D[]' expression to type `MonoTouch.Foundation.NSObject[]'
so ändere ich das von mir selbst,
ApiDefinition.cs
[Export ("addMarshals:num:")]
void AddMarshals (IntPtr marshals, int numCoord);
Extra.cs
public unsafe void AddMarshals (Marshal3D[] marshals) {
var count = marshals.Length;
fixed (Marshal3D* ptr = &marshals[0])
AddMarshals ((IntPtr)ptr, count);
}
dies gut funktioniert.
Aber kann dieser Ansatz nicht für die Verwendung
-(id)initWithMarshals:(Marshal3D *)marshals num:(int)numCoord;
weil es Konstruktor ist, erlauben keine Logik hinzufügen, bevor übergeordnete Methode aufrufen.
Gibt es eine Möglichkeit, das zu beheben?
Verwenden Sie "Factory-Muster" ist am besten?
3.
[Export ("getMarshals:")]
[Internal]
int GetMarshals (IntPtr getMarshals);
und
public partial class MarshalTest : NSObject {
public unsafe Marshal3D [] GetMarshals() {
var count = this.StoredNumber();
var array = new Marshal3D [count];
fixed (Marshal3D* ptr = &array[0])
GetMarshals ((IntPtr) ptr);
return array;
}
}
nicht funktioniert.
beendet ohne Fehler in der RUNNIG-Phase.
Ich denke
Marshal3D* ptr = &array[0]
ein Zeiger ist, aber
-(int)getMarshals:(Marshal3D **)getMarshals;
braucht Zeiger-of-Zeiger.
Ist es nicht richtig?
Rolf, vielen Dank für die Beantwortung! Ich habe ein paar Fragen, also habe ich meine erste Frage bearbeitet. – kochizufan
@kochizufan: Ich habe meine Antwort auch aktualisiert –
Vielen Dank, alle von ihnen funktioniert sehr gut, aber eine Frage. Im 1. Fall von Extra.cs ist der zurückgegebene IntPtr-Wert von GetPointer-Funktion außerhalb des "festen" Blocks. Besteht keine Gefahr von SEGV, wenn GC auftritt? – kochizufan