0

I have an Xamarin.iOS application, and I want to reference a binding project so that I can use a .a file in my project. But I get this error when I try to build:

linker command failed with exit code 1 (use -v to see invocation) /Users/darius/Mobile-MyApp/Source/MyApp/MyApp.Touch/MTOUCH: Error MT5216: Native linking failed for '/Users/darius/Mobile-MyApp/Source/MyApp/MyApp.Touch/obj/iPhone/Debug/device-builds/iphone7.1-11.0.3/mtouch-cache/arm64/libAcrCloudSdkIosBinding.dll.dylib'. Please file a bug report at http://bugzilla.xamarin.com (MT5216) (Touchshop.Touch)

I checked what architectures the .a file supports with this command line:

xcrun -sdk iphoneos lipo -info libACRCloud_IOS_SDK.a

and it outputs:

Architectures in the fat file: libACRCloud_IOS_SDK.a are: armv7 i386 x86_64 arm64

I put the .a in the NativeReferences folder.

Here is my ApiDefinition.cs:

using System;

using UIKit;
using Foundation;
using ObjCRuntime;
using CoreGraphics;

namespace AcrCloudSdkIos
{
// typedef void (^ACRCloudResultBlock)(NSString *, ACRCloudResultType);
delegate void ACRCloudResultBlock(string arg0, ACRCloudResultType arg1);

// typedef void (^ACRCloudResultWithFpBlock)(NSString *, NSData *);
delegate void ACRCloudResultWithFpBlock(string arg0, NSData arg1);

// typedef void (^ACRCloudStateBlock)(NSString *);
delegate void ACRCloudStateBlock(string arg0);

// typedef void (^ACRCloudVolumeBlock)(float);
delegate void ACRCloudVolumeBlock(float arg0);

// @interface ACRCloudConfig : NSObject
[BaseType(typeof(NSObject))]
interface ACRCloudConfig
{
    // @property (retain, nonatomic) NSString * accessKey;
    [Export("accessKey", ArgumentSemantic.Retain)]
    string AccessKey { get; set; }

    // @property (retain, nonatomic) NSString * accessSecret;
    [Export("accessSecret", ArgumentSemantic.Retain)]
    string AccessSecret { get; set; }

    // @property (retain, nonatomic) NSString * host;
    [Export("host", ArgumentSemantic.Retain)]
    string Host { get; set; }

    // @property (retain, nonatomic) NSString * audioType;
    [Export("audioType", ArgumentSemantic.Retain)]
    string AudioType { get; set; }

    // @property (retain, nonatomic) NSString * homedir;
    [Export("homedir", ArgumentSemantic.Retain)]
    string Homedir { get; set; }

    // @property (retain, nonatomic) NSString * uuid;
    [Export("uuid", ArgumentSemantic.Retain)]
    string Uuid { get; set; }

    // @property (retain, nonatomic) NSString * protocol;
    [Export("protocol", ArgumentSemantic.Retain)]
    string Protocol { get; set; }

    // @property (retain, nonatomic) NSDictionary * params;
    [Export("params", ArgumentSemantic.Retain)]
    NSDictionary Params { get; set; }

    // @property (assign, nonatomic) ACRCloudRecMode recMode;
    [Export("recMode", ArgumentSemantic.Assign)]
    ACRCloudRecMode RecMode { get; set; }

    // @property (assign, nonatomic) NSInteger requestTimeout;
    [Export("requestTimeout")]
    nint RequestTimeout { get; set; }

    // @property (assign, nonatomic) NSInteger prerecorderTime;
    [Export("prerecorderTime")]
    nint PrerecorderTime { get; set; }

    // @property (assign, nonatomic) _Bool keepPlaying;
    [Export("keepPlaying")]
    bool KeepPlaying { get; set; }

    // @property (copy, nonatomic) ACRCloudResultBlock resultBlock;
    [Export("resultBlock", ArgumentSemantic.Copy)]
    ACRCloudResultBlock ResultBlock { get; set; }

    // @property (copy, nonatomic) ACRCloudStateBlock stateBlock;
    [Export("stateBlock", ArgumentSemantic.Copy)]
    ACRCloudStateBlock StateBlock { get; set; }

    // @property (copy, nonatomic) ACRCloudVolumeBlock volumeBlock;
    [Export("volumeBlock", ArgumentSemantic.Copy)]
    ACRCloudVolumeBlock VolumeBlock { get; set; }

    // @property (copy, nonatomic) ACRCloudResultWithFpBlock resultFpBlock;
    [Export("resultFpBlock", ArgumentSemantic.Copy)]
    ACRCloudResultWithFpBlock ResultFpBlock { get; set; }
}

// @interface ACRCloudRecognition : NSObject
[BaseType(typeof(NSObject))]
interface ACRCloudRecognition
{
    // -(id)initWithConfig:(ACRCloudConfig *)config;
    [Export("initWithConfig:")]
    IntPtr Constructor(ACRCloudConfig config);

    // -(void)startPreRecord:(NSInteger)recordTime;
    [Export("startPreRecord:")]
    void StartPreRecord(nint recordTime);

    // -(void)stopPreRecord;
    [Export("stopPreRecord")]
    void StopPreRecord();

    // -(void)startRecordRec;
    [Export("startRecordRec")]
    void StartRecordRec();

    // -(void)stopRecordRec;
    [Export("stopRecordRec")]
    void StopRecordRec();

    // -(void)stopRecordAndRec;
    [Export("stopRecordAndRec")]
    void StopRecordAndRec();

    // -(NSString *)recognize:(char *)buffer len:(int)len;
    [Export("recognize:len:")]
    unsafe string Recognize(NSObject buffer, int len);

    // -(NSString *)recognize:(NSData *)pcm_data;
    [Export("recognize:")]
    string Recognize(NSData pcm_data);

    // -(void)recognize_fp:(NSData *)fingerprint resultBlock:(ACRCloudResultBlock)resultBlock;
    [Export("recognize_fp:resultBlock:")]
    void Recognize_fp(NSData fingerprint, ACRCloudResultBlock resultBlock);

    // -(NSString *)recognize_fp:(NSData *)fingerprint;
    [Export("recognize_fp:")]
    string Recognize_fp(NSData fingerprint);

    // +(NSData *)get_fingerprint:(char *)pcm len:(int)len;
    [Static]
    [Export("get_fingerprint:len:")]
    unsafe NSData Get_fingerprint(NSObject pcm, int len);

    // +(NSData *)get_fingerprint:(NSData *)pcm;
    [Static]
    [Export("get_fingerprint:")]
    NSData Get_fingerprint(NSData pcm);

    // +(NSData *)get_fingerprint:(char *)pcm len:(unsigned int)len sampleRate:(unsigned int)sampleRate nChannel:(short)nChannel;
    [Static]
    [Export("get_fingerprint:len:sampleRate:nChannel:")]
    unsafe NSData Get_fingerprint(NSObject pcm, uint len, uint sampleRate, short nChannel);

    // +(NSData *)get_fingerprint:(NSData *)pcm sampleRate:(unsigned int)sampleRate nChannel:(short)nChannel;
    [Static]
    [Export("get_fingerprint:sampleRate:nChannel:")]
    NSData Get_fingerprint(NSData pcm, uint sampleRate, short nChannel);

    // +(NSData *)resample:(NSData *)pcm sampleRate:(unsigned int)sampleRate nChannel:(short)nChannel;
    [Static]
    [Export("resample:sampleRate:nChannel:")]
    NSData Resample(NSData pcm, uint sampleRate, short nChannel);

    // +(NSData *)resample:(char *)pcm len:(unsigned int)len sampleRate:(unsigned int)sampleRate nChannel:(short)nChannel;
    [Static]
    [Export("resample:len:sampleRate:nChannel:")]
    unsafe NSData Resample(NSObject pcm, uint len, uint sampleRate, short nChannel);

    // +(NSData *)resample_bit32:(char *)pcm len:(unsigned int)bytes sampleRate:(unsigned int)sampleRate nChannel:(short)nChannel isFloat:(_Bool)isFloat;
    [Static]
    [Export("resample_bit32:len:sampleRate:nChannel:isFloat:")]
    unsafe NSData Resample_bit32(NSObject pcm, uint bytes, uint sampleRate, short nChannel, bool isFloat);
}

}

And Structs.cs:

using System;

namespace AcrCloudSdkIosBinding
{
    public enum ACRCloudRecMode : uint
    {
        remote = 0,
        local = 1,
        both = 2,
        advance_remote = 3
    }

    public enum ACRCloudResultType
    {
        error = -1,
        none = 0,
        audio = 1,
        live = 2,
        audio_live = 3
    }

    public enum HTTPResumeType
    {
        error = -1,
        resume = 0,
        restart = 1,
        success = 2
    }
}

Here is the source for it, the .a file can be found there too (libACRCloud_IOS_SDK.a). And Here is the cocoapod for it.

Drake
  • 2,679
  • 4
  • 45
  • 88
  • I use your ApiDefinition.cs and Structs.cs and the libACRCloud_IOS_SDK.a file downloaded from Cocoapods. In the Release + Device configuration, the successful Build without any error. – sunyt Nov 03 '17 at 09:39
  • But if you try to do `x = new ACRCloudRecognition()` it won't compile. I posted the solution below. – Drake Nov 05 '17 at 03:08

2 Answers2

2

After a week of hacking at this, I found the solution. I opened the source code of the native project (Swift) in Xcode and noticed that it was referencing libc++.tbd. So all I had to do is set -lc++ in the Linker Flags for the referencing .a library in Visual Studio (Right click on the library -> Properties -> Linker Flags).

Also, make sure that you are giving the appropriate privileges in your info.plist that your library needs. It would just crash on me without giving any error before I set the privileges that it needed.

The tool that Cole Xia referenced is worth looking at too, because I had to manually pick out the interfaces I needed in the generated ApiDefinition.cs because it was filled with junk that I didn't need, and fix a few things with it too. So I gave him the bounty points for that. I guess the tool didn't work for this library because of the referencing libc++.tbd.

Drake
  • 2,679
  • 4
  • 45
  • 88
1

Try to update Xcode and Sharpie to the latest version, and then recreate the binding project.

here may be helpful.

Update:

I try to use Sharpie with cocoapods following official link.

  • When I try to bind famous third-party library like AFNetworking , it generates a folder named Binding ,inside it we can find the ApiDefinitions , StructsAndEnums and the library.

    sharpie pod -d /Users/yourName/Desktop/FolderName init ios AFNetworking && sharpie pod -d /Users/yourName/Desktop/FolderName bind
    

    enter image description here

  • When I try to bind acrcloud , it didn't generate the binding folder.

    sharpie pod -d /Users/yourName/Desktop/FolderName init ios acrcloud_ios_sdk && sharpie pod -d /Users/yourName/Desktop/FolderName bind
    

    enter image description here

So I guess there may be something wrong with acrcloud sdk.

ColeX
  • 14,062
  • 5
  • 43
  • 240
  • I updated both but same error. Is there possible something wrong in my `ApiDefinition.cs` that I need to fix? – Drake Oct 26 '17 at 15:24
  • @Darius would you mind to share the lib file?I will test by my side and get you back – ColeX Oct 26 '17 at 15:30
  • I added a link to download it at the end of my post. Thanks! – Drake Oct 26 '17 at 15:34
  • @Darius try to create the binding project with the tool in that link I provided – ColeX Oct 26 '17 at 15:35
  • I added a link to the source at the bottom of my post. – Drake Oct 26 '17 at 15:48
  • I update sharpie to 3.4.0 and got the same issue as [here](https://stackoverflow.com/questions/46821529/trouble-binding-objective-c-library-to-c-sharp-with-objective-sharpie),it generates a lot of code which are mostly useless. I suggest you to follow the video to use the [tool](https://github.com/alexsorokoletov/objc-automatic) to see if it works. – ColeX Oct 26 '17 at 16:37
  • I just realized that the source code in the Github was updated 4 days ago, same with what is on cocoapod...is it possible that the problem we were experiencing was due to versioning mismatch? – Drake Oct 31 '17 at 04:12
  • You can have a try and let me know the result. – ColeX Oct 31 '17 at 04:27
  • I used the tool you suggested and it didn't work when I executed the script. Didn't give a very informative error message either... I'm running out of ideas...this was so much easier to do with the Android version – Drake Oct 31 '17 at 04:52
  • I just realized that I'm able to build if I don't reference anything in the binding project...so I probably never had it working to begin with. – Drake Oct 31 '17 at 15:31
  • I made some progress. Can you try something on your side and tell me if it works for you please? Download this source: https://github.com/alexsorokoletov/objc-automatic and run `pod try acrcloud_ios_sdk` and then `mozroots --import --sync` and then `sudo nuget update -Self` and then `sh bind.sh POD=acrcloud_ios_sdk` - Are the binding generated successfully for you? (they won't for me..). I'd really appreciate it if you can help me on this one. – Drake Nov 02 '17 at 04:41
  • @Darius okay,I will try later and get you back – ColeX Nov 02 '17 at 04:53
  • I just realized something else. If I comment-out the entire `interface ACRCloudRecognition` in my `ApiDefinition.cs`, I am then able to compile and use the other signature (`interface ACRCloudConfig`). So it must be something in the `interface ACRCloudRecognition` that I need to change, and I reckon that it's the methods that are marked with `unsafe`. The original parameters in those functions were `char*` but I changed them to `NSObject` because it wouldn't compile otherwise...do you know what I can change `char*` to make a proper signature? – Drake Nov 02 '17 at 19:00