Bug 24943 - DllImport __Internal on iOS means we have to recompile PInvoke library only for iOS
Summary: DllImport __Internal on iOS means we have to recompile PInvoke library only f...
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: master
Hardware: PC Windows
: Normal normal
Target Milestone: Future Cycle (TBD)
Assignee: Rolf Bjarne Kvinge [MSFT]
Depends on:
Reported: 2014-11-30 21:23 UTC by Virgile Bello
Modified: 2017-10-24 08:50 UTC (History)
7 users (show)

Is this bug a regression?: ---
Last known good build:

non-working dllmap (12.87 KB, application/x-zip-compressed)
2016-06-10 10:01 UTC, Virgile Bello

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Virgile Bello 2014-11-30 21:23:52 UTC

Currently, if I was to make a PInvoke library (DllImport) with native code, we always have to compile the PInvoke C# library twice with ugly #ifdef because iOS expect __Internal instead of dll name in DllImport().

Would it be possible to have a way to map certain library (let's say A.dll) to __Internal automatically when on iOS?
Somehow similar to how dllmaps (http://www.mono-project.com/docs/advanced/pinvoke/dllmap/ ) hides platform library mapping differences outside of the MSIL DllImport code.

I would be happy with either command line parameter, a configuration file, or "LinkWith"-like attributes, as long as this configuration is done on the link target (final executable using the library) and not the library itself (that we want to keep platform dependent).

That would allow to reuse same MSIL PInvoke library on any platform (with PCL).

Comment 1 Rolf Bjarne Kvinge [MSFT] 2014-12-01 03:35:28 UTC
Have you tried using dllmaps? AFAICT that should already work.

Also note that you only need 1 #ifdef, since you can use a constant string for the dll name:

#if __IOS__
     const string DllName = "__Internal";
    const string DllName = "dllname.dll";

[DllImport (DllName)]
static extern void myfunc ();

This will however not make it possible to build only once though.
Comment 2 Virgile Bello 2014-12-01 03:55:43 UTC
We already do the #ifdef trick, but as you mentioned it still requires two MSIL dll.

And I am not even mentionning if DllImport was not a const (in existing projects), we have to maintain a huge fork to have it that way.

However, I didn't knew dllmap might be working, I will check into that.
Comment 3 Sebastien Pouliot 2016-05-26 01:26:02 UTC
We have not received the requested information. If you are still experiencing this issue please provide all the requested information and re-open the bug report. Thanks!
Comment 4 Virgile Bello 2016-06-10 01:59:53 UTC
Please let me know what requested info is missing and would be happy to provide it.

Tried again to use a dllmap on iOS, it didn't seem to work.

Could we have a way to either:
- Use a dllmap (in the .dll binding project)
- Or at least some mtouch parameter to remap?

We still have to maintain a separate .dll set of several libraries (SharpFont=>freetype.dll, BulletPhysics etc...) only due to iOS, all other platforms are happy with the same PCL library.
Comment 5 Rolf Bjarne Kvinge [MSFT] 2016-06-10 08:34:39 UTC
Could you attach your solution using dllmap that doesn't work?
Comment 6 Virgile Bello 2016-06-10 10:01:21 UTC
Created attachment 16267 [details]
non-working dllmap

Attached a simple test case using OpenGL ES:

// This function work
[DllImport("/System/Library/Frameworks/OpenGLES.framework/OpenGLES", ExactSpelling = true)]
private static extern void glViewport(int x, int y, int width, int height);

// This funciton doesn't work
[DllImport("libGLESv2.dll", ExactSpelling = true)]
private static extern int glGetError();

We have a App.config with <dllmap dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />

Let me know if I am doing something wrong.
Note that this should also work by combining App.config from .dll (i.e. I should be able to define this dllmap directly in the calling library even though it is not the final executable, just like OpenTK would do).

Note: I suspect you have some hardcoded dllmap since Xamarin version of OpenTK seems to be happy with libGLESv2.dll, or maybe it works only in limited cases?
Comment 7 Rolf Bjarne Kvinge [MSFT] 2016-06-10 10:27:58 UTC
Comment 8 Rolf Bjarne Kvinge [MSFT] 2016-10-31 12:09:57 UTC
I tried your test case, and it seems to work fine for me, both on device and in the simulator (the app launches and I see spinning cubes).

What exactly is the behavior you're seeing?
Comment 9 Alex Soto [MSFT] 2016-12-07 03:19:44 UTC
We have not received the requested information. If you are still 
experiencing this issue please provide all the requested information 
and re-open the bug report. Thanks!
Comment 10 jacanosalado 2017-10-23 14:06:43 UTC
Hi, sorry for reopening this report again but I get to the same point.

I have to duplicate my PInvoke wrapper dll because of the __Internal thing.

Dllmap work for ios.

But what Virgile Bello and I are looking for is something like this:

  <dllmap dll="libnative" os="ios" target="__Internal"/>

Note the "automatically when on iOS" in Virgile Bello's question.

I tried the os="ios" and it doesn't work.

Is there any workaround or method to do this, apart from duplicating the dll using the #ifdef with a constant in the dll name. I consider this a waste.
Comment 11 Rolf Bjarne Kvinge [MSFT] 2017-10-23 15:47:18 UTC
One solution is to have two different dllmaps.

OTOH I believe os="osx" is the os for iOS [1] (which is not ideal, since it won't work if you want to run on macOS as well).

Which platforms do you target?

[1]: https://github.com/mono/mono/blob/5edb2a54dbbe350789bc498cd8b32f0829b5b3e1/mono/metadata/mono-config.c#L28
Comment 12 jacanosalado 2017-10-23 17:53:52 UTC
I'm targeting: android, ios, linux, mac, windows classic and universal.
I also want to package it using nuget so I think this workaround is not going to work for me :S

More ideas to avoid the extra ios dll? For the rest of the platforms I'm using the exact same dll. ios is the single one that require the extra compilation of another exact lib but with the __Internal thing.
Comment 13 jacanosalado 2017-10-23 21:09:07 UTC
Thinking about multiple dllmap files I just came to an idea that could work for nuget deployment.

Add a target only for XamariniOS that includes a dll map file without the os node.
I mean, use the nuget capability of conditionally including a target for a given platform to add the specific dllmap for ios and other dll map file for win, mac and linux.

I'm going to give a try :D
Comment 14 jacanosalado 2017-10-23 21:41:01 UTC
Working like a charm!
Thanks Rolf :D
Comment 15 Rolf Bjarne Kvinge [MSFT] 2017-10-24 08:50:17 UTC
Great, thanks for letting us know it works :)