Bug 3651 - P/Invoke of function in static-linked library results in EntryPointNotFoundException
Summary: P/Invoke of function in static-linked library results in EntryPointNotFoundEx...
Status: RESOLVED INVALID
Alias: None
Product: iOS
Classification: Xamarin
Component: Tools ()
Version: 5.2
Hardware: PC Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2012-02-26 17:03 UTC by Jordan Phillips
Modified: 2012-02-28 06:42 UTC (History)
2 users (show)

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


Attachments
Minimal test project to reproduce issue (2.72 MB, application/zip)
2012-02-26 17:03 UTC, Jordan Phillips
Details


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:
Status:
RESOLVED INVALID

Description Jordan Phillips 2012-02-26 17:03:40 UTC
Created attachment 1424 [details]
Minimal test project to reproduce issue

I have a pre-built universal (simulator + armv7) native library that includes extern "C" functions, along with C++ code (requiring that it be linked with libstdc++). I have included the native reference in the project, and I am attempting to P/Invoke a function using the following code:

	[DllImport("__Internal")]
        public static extern void cvReleaseImage(ref IntPtr image);

...

	IntPtr ptr = IntPtr.Zero;
	cvReleaseImage(ref ptr);

When executed on the simulator, the call to cvReleaseImage results in an EntryPointNotFoundException.

Running nm on the .a file, I see: 

> nm libopencv_core.a | grep cvReleaseImage
0002920b s __ZZ14cvReleaseImageE8__func__
000291e8 s __ZZ20cvReleaseImageHeaderE8__func__
0001112c T _cvReleaseImage
000108fc T _cvReleaseImageHeader
nm: no name list
         U _cvReleaseImage
0003d8e8 s __ZZ14cvReleaseImageE8__func__
0003d8c0 s __ZZ20cvReleaseImageHeaderE8__func__
00018de0 T _cvReleaseImage
0003e790 S _cvReleaseImage.eh
00018430 T _cvReleaseImageHeader
0003e718 S _cvReleaseImageHeader.eh
nm: no name list
         U _cvReleaseImage

Running nm on my compiled executable, I see:

> nm bin/iPhoneSimulator/Debug/LinkingIssue.app/LinkingIssue | grep cvReleaseImage
004cb064 s __ZZ14cvReleaseImageE8__func__
004cb03c s __ZZ20cvReleaseImageHeaderE8__func__
000544d0 t _cvReleaseImage
00053b20 t _cvReleaseImageHeader

The cvReleaseImage symbol appears to be stripped from the final executable, rendering it un-callable at runtime. Oddly, the non-externed mangled symbol is still included, which is resolved as:

> c++filt __ZZ14cvReleaseImageE8__func__
cvReleaseImage::__func__

I've tried adding -nostrip and -nosymbolstrip, but neither option had any effect on the cvReleaseImage symbols included in the final executable. I've also tried changing the EntryPoint of the DllImport to the mangled function name, but it resulted in the same EntryPointNotFoundException.

A minimal test project is attached.
Comment 1 Rolf Bjarne Kvinge [MSFT] 2012-02-27 08:13:56 UTC
It looks very similar to this: http://stackoverflow.com/questions/5085528/monotouch-pinvoke-system-entrypointnotfoundexception

The symbol is in the binary, it's just local instead of global (t vs T). I can't see anything wrong with your code, but it *might* have something to do with how the static library is compiled. I'll investigate a bit more.
Comment 2 Rolf Bjarne Kvinge [MSFT] 2012-02-27 18:50:53 UTC
I just tried creating a very simple native library, and it worked fine, so I think it has something to do with how your native library was built.

That said, nm is reporting something strange about the *.a file

0001112c T _cvReleaseImage
              U _cvReleaseImage

The method seems to exist, but at the same time it's unresolved.
Comment 3 Jordan Phillips 2012-02-28 00:04:36 UTC
The .a file was built using this build script: https://github.com/BloodAxe/OpenCV-iOS-build-script

It runs lipo to combine the ARMv7 and Simulator builds into a single universal .a file. Could this be causing the problem? That would at least explain why not all of the symbols are making it across to the final executable, since not all of them are for the target architecture.

I'll give it a shot tonight with a non-combined .a file (simulator only) - but it seems like that would prevent the use of the "Native References" feature, since it would need to reference a different .a file for the device and simulator builds. Is there a way to use "Native References" for simulator and device without resorting to the old style method of adding the build flags manually?
Comment 4 Jordan Phillips 2012-02-28 00:53:11 UTC
A non-universal .a file (simulator only) works correctly, with the following nm output:

> nm bin/iPhoneSimulator/Debug/LinkingIssue.app/LinkingIssue | grep cvReleaseImage
00556e30 s __ZZ14cvReleaseImageE8__func__
00556e08 s __ZZ20cvReleaseImageHeaderE8__func__
00063180 T _cvReleaseImage
000627d0 T _cvReleaseImageHeader


Thanks for looking in to this, so I suppose this issue boils down to:

1. Would it be possible to support whatever it is the lipo tool does so a "universal" binary can be linked against?

2. Is there a way to use the "Native References" feature of monodevelop, to reference different .a files for different platforms?
Comment 5 Jordan Phillips 2012-02-28 01:22:57 UTC
It looks like I spoke too soon in my last comment - in addition to the simulator build working, the universal build I just created (using the aforementioned build script) works as well. The pre-built .a file is the only one that doesn't appear to work, at this point.

Thanks for your help - it now sounds like this is just something wrong with the original pre-built .a file.
Comment 6 Rolf Bjarne Kvinge [MSFT] 2012-02-28 06:42:50 UTC
Thanks for confirming it, I'll close this bug then.