Binding an Objective-C char-array type global field

RakemanRakeman USMember
edited May 2015 in Xamarin.iOS

We've an Objective-C library with a byte-array type global field as follows:

extern const unsigned char LibraryApplicationKey[]

We produced an ApiDefinition file using Objective Sharpie. It bound the field as follows:

partial interface Constants
{
    [Field ("LibraryApplicationKey")]
    byte[] LibraryApplicationKey { get; }
}

The build succeeded. But the resultant DLL didn't contain the Constants class. Also, the field is a get/set field and not read-only.

So then we tried applying the [Static] attribute to the Constants class as given here and added a set to the LibraryApplicationKey property. We even tried using _"__Internal"_ as the library name. All that didn't work either. We got the following error.

Error BI1014: btouch: Unsupported type for Fields: global::System.Byte[] (BI1014)

How can we bind this field?

Answers

  • RolfBjarneKvingeRolfBjarneKvinge USXamarin Team Xamurai

    Try binding it as IntPtr instead of byte[].

  • RakemanRakeman USMember

    Thanks very much, @RolfBjarneKvinge, for your answer.

    We tried that. The binding project built successfully. In the demo application, we assigned the Handle of an NSString to this field. We got an error at the site of assignment while building:

    Native linking failed, undefined symbol: _SpeechKitApplicationKey. This symbol was referenced by the managed member > XSpeechBinding.Constants.SpeechKitApplicationKey. Please verify that all the necessary frameworks have been referenced > and native libraries linked. (MT5214) (SpeechDemo.iOS)

    We are trying to bind Dragon, the Nuance iOS SDK (the latest one), for speech recognition. It has a global field called SpeechKitApplicationKey (with no leading underscore as shown in the above error) of type char-array as shown in previous post.

    Please could you take a look and help us?

  • RolfBjarneKvingeRolfBjarneKvinge USXamarin Team Xamurai

    Adding __Internal as the library name should fix the build error:

    [Field ("SpeechKitApplicationKey", "__Internal")]
    IntPtr SpeechKitApplicationKey { get; set; }
    

    however assigning the Handle of an NSString is wrong, you must allocate a block of native memory (System.Runtime.InteropServices.Marshal.AllocHGlobal) and copy the bytes you want into that memory (System.Runtime.InteropServices.Marshal.Copy) before assigning the pointer to that memory to the SpeechKitApplicationKey property.

  • RakemanRakeman USMember

    Ok; thanks for your reply. We've already specified __Internal as the library name. We still get that build error. I've attached the binding library hereby. We think the issue is in our binding.

    This is how we're calling it:

    IntPtr hglobal = System.Runtime.InteropServices.Marshal.AllocHGlobal (128);
    
    System.Runtime.InteropServices.Marshal.Copy (
        (new [] {//app key
        }).Select (
            element => Convert.ToByte (element)).ToArray (),
        0, 
        hglobal,
        64);
    
    XSpeechBinding.Constants.SpeechKitApplicationKey = hglobal; //build error on this line
    
    XSpeechBinding.SpeechKit.SetupWithID ("id", "sanbox", "portnumber", false, null);
    

    We would be very grateful to you if you could take out some time and take a quick look at it as we've reached a dead end.

  • RakemanRakeman USMember

    binding library

  • RolfBjarneKvingeRolfBjarneKvinge USXamarin Team Xamurai

    The problem is that SpeechKit.a does not contain a definition for SpeechKitApplicationKey, you're supposed to provide one yourself.

    It's not possible to do that in C#, you'll need to create your own native static library with this single line of code:

    const char* SpeechKitApplicationKey = "mykey";
    

    and then add that library to your binding project.

  • RakemanRakeman USMember

    Thanks, @RolfBjarneKvinge. Putting the key in a separate static library worked!

    However, using a const char* didn't. We had to declare it as const unsigned char SpeechKitApplicationKey[] and pass in the key as a hex array rather than a string literal.

    We also removed the corresponding bindings from the binding project. We decided we'd just update the key directly in the static library project if needed.

    Thanks again for all your help!

  • mwesolowskimwesolowski PLMember ✭✭
    How LibraryApplicationKey from the beginning is related to the later SpeechKitApplicationKey?
  • mwesolowskimwesolowski PLMember ✭✭

    @RolfBjarneKvinge could you please look at my question?

  • prupleBoyprupleBoy USMember

    我集成高德地图SDK在Xamarin中绑定遇到这个错,出现的问题是接口同名,合并或区别命名就好

Sign In or Register to comment.