For some reason i need to use this native framework in my Xamarin.iOS app and the problem comes, that i have no idea how to make bindings properly.
So as i understood correctly, this framework also uses another one framework and i'm little bit confused, what exactly i need to do?
Questions :
- Do i need to implement static library(is this possible to do with native frameworks) as it shows on official documentation of Xamarin ?
- Can i make bindings for native framework that is using another framework too or i need to implement them separately?
- Maybe i should re-write all these native frameworks into C# version?!? (But here's appears another problem, frameworks uses ObjC and is hard to reproduce in C# for me)
- What is the best approach to achieve my goal?(maybe its not described and you can tell me more).
Any advice? Thanks!
OK, finally i have made a Static Library, but something is going wrong and i can't use it on Emulator at current moment. :(
I will explain step by step how i have made an static library :
- I got all source files from this repository.
In Xcode IDE i have made Static Library project and after this i have copied all source files from repository to my project.
Via Carthage i have download this framework(As i have explained, source files uses this framework) and also i have added new category in Build Phases -> Copy Files (where i have selected framework) into my Static Library . And builded successfully(On Deployment Target 10.2)
.
Next, i have made MakeFile and successfully generated four Fat Binary .a library's without any problem.
Xcrun command shows :
xcrun -sdk iphoneos lipo -info libOSMapKitAdapter.a
Architectures in the fat file: libOSMapKitAdapter.a are: i386 armv7 x86_64 arm64
Then i have created Binding Library project in Xamarin and added Fat Binary Static Library as Native Reference(i will show my .csproj file below) and also i have put the same for framework(i have copied inside to project path) that is linked inside of Static Library (maybe it's redundant?)
Also , i have made additional file that is called OSTransformation.framework.linkwith.cs with code:
Via Objective Sharpie i have been generated ApiDefinition.cs and Structs.cs.
Command :
sharpie bind --output=OSMapKitAdapter --namespace=OSMapKitAdapter --sdk=iphoneos10.2 /MyPath/OSMapKitAdapter/OSMapKitAdapter/*.h
And the result is :
Parsing 5 header files...
Binding...
[write] ApiDefinitions.cs
[write] StructsAndEnums.cs
Binding Analysis:
Automated binding is complete, but there are a few APIs which have been flagged with [
Verify] attributes. While the entire binding should be audited for best API design
practices, look more closely at APIs with the following Verify attribute hints:
ConstantsInterfaceAssociation (1 instance):
There's no foolproof way to determine with which Objective-C interface an extern
variable declaration may be associated. Instances of these are bound as [Field]
properties in a partial interface into a nearby concrete interface to produce a more
intuitive API, possibly eliminating the 'Constants' interface altogether.
PlatformInvoke (4 instances):
In general P/Invoke bindings are not as correct or complete as Objective-C bindings (
at least currently). You may need to fix up the library name (it defaults to '__
Internal') and return/parameter types manually to conform to C calling conventionsfor
the target platform. You may find you don't even want to expose the C API in your
binding, but if you do, you'll probably also want to relocate the definition to a
more appropriate class and expose a stronger type-safe wrapper. For P/Invoke guidance,
see http://www.mono-project.com/docs/advanced/pinvoke/.
Once you have verified a Verify attribute, you should remove it from the binding source
code. The presence of Verify attributes intentionally cause build failures.
For more information about the Verify attribute hints above, consult the Objective
Sharpie documentation by running 'sharpie docs' or visiting the following URL:
http://xmn.io/sharpie-docs
Submitting usage data to Xamarin...
Submitted - thank you for helping to improve Objective Sharpie!
Done.
Generated code of ApiDefinition.cs looks like:
[Static]
[Verify (ConstantsInterfaceAssociation)]
partial interface Constants
{
// extern double OSMapKitAdapterVersionNumber;
[Field ("OSMapKitAdapterVersionNumber", "__Internal")]
double OSMapKitAdapterVersionNumber { get; }
// extern const unsigned char [] OSMapKitAdapterVersionString;
[Field ("OSMapKitAdapterVersionString", "__Internal")]
byte[] OSMapKitAdapterVersionString { get; }
}
// @interface OSTileOverlay : MKTileOverlay
[BaseType (typeof(MKTileOverlay))]
interface OSTileOverlay
{
// @property (assign, nonatomic) BOOL clipOverlay;
[Export ("clipOverlay")]
bool ClipOverlay { get; set; }
// -(instancetype _Nonnull)initWithAPIKey:(NSString * _Nonnull)apiKey product:(OSMapProduct)product __attribute__((objc_designated_initializer));
[Export ("initWithAPIKey:product:")]
[DesignatedInitializer]
IntPtr Constructor (string apiKey, OSMapProduct product);
}
// @interface OSMapViewRegionRestriction : NSObject
[BaseType (typeof(NSObject))]
interface OSMapViewRegionRestriction
{
// @property (readonly, nonatomic) MKCoordinateRegion initialRegion;
[Export ("initialRegion")]
MKCoordinateRegion InitialRegion { get; }
// -(void)updateMapViewRegionIfRequired:(MKMapView * _Nonnull)mapView;
[Export ("updateMapViewRegionIfRequired:")]
void UpdateMapViewRegionIfRequired (MKMapView mapView);
}
// @interface OSMapKitAdapter : NSObject
[BaseType (typeof(NSObject))]
interface OSMapKitAdapter
{
}
Structs.cs :
[Native]
public enum OSMapProduct : nint
{
Road,
Outdoor,
Light,
Night
}
static class CFunctions
{
// extern NSString * NSStringFromOSMapProduct (OSMapProduct product);
[DllImport ("__Internal")]
[Verify (PlatformInvoke)]
static extern NSString NSStringFromOSMapProduct (OSMapProduct product);
// extern CLLocationCoordinate2D OSUpperLeftCorner ();
[DllImport ("__Internal")]
[Verify (PlatformInvoke)]
static extern CLLocationCoordinate2D OSUpperLeftCorner ();
// extern CLLocationCoordinate2D OSLowerRightCorner ();
[DllImport ("__Internal")]
[Verify (PlatformInvoke)]
static extern CLLocationCoordinate2D OSLowerRightCorner ();
// extern MKMapRect OSMapRectForUK ();
[DllImport ("__Internal")]
[Verify (PlatformInvoke)]
static extern MKMapRect OSMapRectForUK ();
}
OK, now i got compile errors and as it shows on official tutorial of Xamarin bindings , i need to check Fields with [Verify] Attribute and after resolving problem with them needs to remove this Attribute , also add Protocol attribute and etc.
New version of ApiDefinition.cs :
[Static]
//[Verify(ConstantsInterfaceAssociation)]
partial interface Constants
{
// extern double OSMapKitAdapterVersionNumber;
[Field("OSMapKitAdapterVersionNumber", "__Internal")]
double OSMapKitAdapterVersionNumber { get; }
// extern const unsigned char [] OSMapKitAdapterVersionString;
[Field("OSMapKitAdapterVersionString", "__Internal")]
IntPtr OSMapKitAdapterVersionString { get; }
}
// @interface OSTileOverlay : MKTileOverlay
[BaseType(typeof(MKTileOverlay))]
[Protocol]
interface OSTileOverlay
{
// @property (assign, nonatomic) BOOL clipOverlay;
[Export("clipOverlay")]
bool ClipOverlay { get; set; }
// -(instancetype _Nonnull)initWithAPIKey:(NSString * _Nonnull)apiKey product:(OSMapProduct)product __attribute__((objc_designated_initializer));
[Export("initWithAPIKey:product:")]
[DesignatedInitializer]
IntPtr Constructor(string apiKey, OSMapProduct product);
}
// @interface OSMapViewRegionRestriction : NSObject
[BaseType(typeof(NSObject))]
[Protocol]
interface OSMapViewRegionRestriction
{
// @property (readonly, nonatomic) MKCoordinateRegion initialRegion;
[Export("initialRegion")]
MKCoordinateRegion InitialRegion { get; }
// -(void)updateMapViewRegionIfRequired:(MKMapView * _Nonnull)mapView;
[Export("updateMapViewRegionIfRequired:")]
void UpdateMapViewRegionIfRequired(MKMapView mapView);
}
// @interface OSMapKitAdapter : NSObject
[BaseType(typeof(NSObject))]
[Protocol]
interface OSMapKitAdapter
{
}
New version of Structs :
#if __UNIFIED__
[Native]
public enum OSMapProduct : long
{
Road,
Outdoor,
Light,
Night
}
#endif
static class CFunctions
{
// extern NSString * NSStringFromOSMapProduct (OSMapProduct product);
[DllImport ("__Internal")]
//[Verify (PlatformInvoke)]
static extern NSString NSStringFromOSMapProduct (OSMapProduct product);
// extern CLLocationCoordinate2D OSUpperLeftCorner ();
[DllImport ("__Internal")]
//[Verify (PlatformInvoke)]
static extern CLLocationCoordinate2D OSUpperLeftCorner ();
// extern CLLocationCoordinate2D OSLowerRightCorner ();
[DllImport ("__Internal")]
//[Verify (PlatformInvoke)]
static extern CLLocationCoordinate2D OSLowerRightCorner ();
// extern MKMapRect OSMapRectForUK ();
[DllImport ("__Internal")]
//[Verify (PlatformInvoke)]
static extern MKMapRect OSMapRectForUK ();
}
The problem is that i'm getting this errors :
Error MT5214: Native linking failed, undefined symbol: _OSMapKitAdapterVersionNumber. This symbol was referenced by the managed member OSTest.Constants.OSMapKitAdapterVersionNumber. Please verify that all the necessary frameworks have been referenced and native libraries linked. (MT5214)
Error MT5214: Native linking failed, undefined symbol: _OSMapKitAdapterVersionString. This symbol was referenced by the managed member OSTest.Constants.OSMapKitAdapterVersionString. Please verify that all the necessary frameworks have been referenced and native libraries linked. (MT5214)
Error MT5202: Native linking failed. Please review the build log. (MT5202)
How looks my .csproj file of_ Xamarin.Bindings_ project :
<ItemGroup>
<Reference Include="System" />
<Reference Include="Xamarin.iOS" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="OSTransformation.framework.linkwith.cs" />
</ItemGroup>
<ItemGroup>
<ObjcBindingApiDefinition Include="ApiDefinition.cs" />
</ItemGroup>
<ItemGroup>
<ObjcBindingCoreSource Include="Structs.cs" />
</ItemGroup>
<ItemGroup>
<NativeReference Include="OSTransformation.framework">
<IsCxx>False</IsCxx>
<Kind>Framework</Kind>
</NativeReference>
<NativeReference Include="..\..\..\MyPath\OSMapKitAdapter\libOSMapKitAdapter.a">
<Kind>Static</Kind>
<SmartLink>False</SmartLink>
</NativeReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.ObjCBinding.CSharp.targets" />
</Project>
It WORKS on real device, but on emulator still get errors this strange errors.
UPD:
Just make sure that you have choose "Link framework SDK only" on linker and works as excepted!
This library is written in pure ObjC. There is only one example written by Swift.
In view of the library code is relatively small, I recommend you re-write into C #