1

I've got a working MonoTouch binding for ZBar up and running, but am having troubles exposing a constant NSString that the Obj-C library defines for use as a Key in an NSDictionary:

inside ZBarReaderController.h:

extern NSString* const ZBarReaderControllerResults;  

I first tried via the actual MonoTouch binding as documented here:

[Static]
interface ZBarSDK
{
    [Field ("ZBarReaderControllerResults")]
    NSString BarcodeResultsKey { get; }
}

Attempting to build the project containing this gave these errors from btouch:

Unhandled Exception: System.ArgumentOutOfRangeException: Argument is out of range.
Parameter name: startIndex
at System.String.Substring (Int32 startIndex) [0x00000] in :0
at Generator.Generate (System.Type type) [0x00000] in :0
at Generator.Go () [0x00000] in :0
at BindingTouch.Main (System.String[] args) [0x00000] in :0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentOutOfRangeException: Argument is out of range.
Parameter name: startIndex
at System.String.Substring (Int32 startIndex) [0x00000] in :0
at Generator.Generate (System.Type type) [0x00000] in :0
at Generator.Go () [0x00000] in :0
at BindingTouch.Main (System.String[] args) [0x00000] in :0

I next attempted to manually call into the code as suggested in this other SO answer.

public static NSString BarcodeResultsKey
{
    get
    {
        var libHandle = Dlfcn.dlopen("libzbar.a",0);
        // I also tried this with "__Internal", rather than "libzbar.a"
        return Dlfcn.GetStringConstant(libHandle, "ZBarReaderControllerResults");
    }
}

It builds and executes fine, but just returns an empty string (as the Dlfcn.GetStringConstant documents it will do if it fails to link).

So, anyone else accessed const strings from a 3rd party Obj-C library?

Community
  • 1
  • 1
Tyson
  • 14,726
  • 6
  • 31
  • 43
  • I assume you've **defined** `ZBarReaderControllerResults` in one of your implementation files, right? And you've linked against that implementation? Also, I wouldn't expect Dlfcn to work with a static library (.a file). It's for dynamic libraries (.dylib file) and you'd need to make sure it's finding that library. See the [dlopen(1) man page](https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/dlopen.3.html). – Ken Thomases Apr 07 '12 at 14:56
  • Well not me personally, no - I'm assuming it's implemented within the zbar SDK library (the libzbar.a library) as that declaration is within the header files supplied with the SDK. And yes, it is definitely linking against that implementation correctly - I've got all the important parts of the library working already (showing the ReaderViewController, capturing barcodes, etc). As for dlfcn and dlopen, I have never used dlopen or done much Unix style native programming before so I wasn't sure - thanks for clearing that up for me, I'll stop investigating that path. – Tyson Apr 07 '12 at 15:03
  • This was filled (thanks) as https://bugzilla.xamarin.com/show_bug.cgi?id=4333 – poupou Apr 08 '12 at 21:27

1 Answers1

2

The generator, btouch, had a limitation (before 5.2.11) for [Field] bindings that requires the namespace to start with MonoTouch..

A quick workaround for this issue is to rename the namespaces from ZBar to MonoTouch.ZBar and the binding definitions will build correctly.

Since iOS applications must link with static libraries (.a) for libraries that are included with an application it's also required to supply a library name "__Internal" in the bindings as described in the documentation.

[Static]
interface ZBarSDK {
    [Field ("ZBarReaderControllerResults", "__Internal")]
    NSString BarcodeResultsKey { get; }
}

There was also a compilation issue (on the generated code) which required some manual adjustment for the library (i.e. you can use null instead of the library name since it's linked inside the main app). This is also fixed in the MonoTouch 5.2.11 release.

With the workarounds (or MonoTouch 5.2.11) and the __Internal change you should be able to use [Field] inside your bindings.

poupou
  • 43,413
  • 6
  • 77
  • 174