Forum Xamarin.Mac


The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

How can I call DCSCopyTextDefinition(_:_:_:) function?

HelloTaxiHelloTaxi Member ✭✭

In Swift, I use following code to translate a word from system dicts:

var word = "hello"
if let result = DCSCopyTextDefinition(nil, word as CFString, CFRange(location: 0, length: word.count)){
    var translation = result.takeRetainedValue() as String

Now, how can I call the DCSCopyTextDefinition function in Xamarin?


  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    So that function is a C API:

    So you need to write a p/invoke. It's a bit involved, let me write this one with a description.

    First here's the prototype:

    CFStringRef DCSCopyTextDefinition(DCSDictionaryRef dictionary, CFStringRef textString, CFRange range);

    and our doc tell us it's in CoreServices.

    So we start with a class:

    static class TextServices

    and then add an attribute telling C# where to find our function:

            [DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]

    now we translate the function into the C# equivalent:

            public static extern IntPtr DCSCopyTextDefinition (IntPtr dictionary, IntPtr textString, CFRange range);

    All of the "Refs" are pointers, so IntPtr. Xamarin.Mac has a CFRange struct, so we can use that.

    Now that's a nightmare to call, so let's wrap it:

            public static string CopyTextDefinition (IntPtr dictionary, string text, CFRange range)
                using (NSString t = (NSString)text) {
                    return ObjCRuntime.Runtime.GetNSObject<NSString> (DCSCopyTextDefinition (dictionary, t.Handle, range));

    The dictionary is some random thing you get elsewhere, so we have to pass the pointer around. We can turn a C# string into an NSString, and NSString and CFString are toll free bridged.

    • We use a using block to make sure the lifetime of our NSString is long enough.
    • We use ObjCRuntime.Runtime.GetNSObject to convert the IntPtr we get back to an NSString (from CFString).

    Now, since I have no way of getting a DCSDictionaryRef, I can't test it, so I don't know if I made any mistakes. That's where I'd start from though.

    P/invokes can be tricky in some cases (callbacks, pointers) and if you mess up it will crash your app in "fun" ways. I'd suggest lots of testing to make sure you get it right.

    Since this is a system framework, you can always request that we bind it at some point via an issue.

  • HelloTaxiHelloTaxi Member ✭✭
    edited July 2019

    @ChrisHamons So pretty cool! And now I learned how to call an OC func also, many many thanks.
    Now here's my code in C#, it works fine:

    var word = "hello";
    var translation = TextServices.CopyTextDefinition(IntPtr.Zero, word, new CoreFoundation.CFRange(0, word.Length));
Sign In or Register to comment.