I built a wrapper for twilio iOS library. I am using the following LinkWith
[assembly: LinkWith ("libTwilioClient.a", LinkTarget.ArmV6 | LinkTarget.ArmV7 | LinkTarget.Simulator, ForceLoad = true ,Frameworks="MediaPlayer SystemConfiguration AVFoundation")]
in Monotouch binding project.
When I created an iPad project that uses above wrapper library I am getting the following errors
Undefined symbols for architecture armv7:
"___divmodsi4", referenced from:
_jbuf_update in libTwilioClient.a(jbuf.o)
_pjmedia_jbuf_get_frame2 in libTwilioClient.a(jbuf.o)
_pjmedia_rtcp_rx_rtp2 in libTwilioClient.a(rtcp.o)
_pjmedia_rtcp_rx_rtcp in libTwilioClient.a(rtcp.o)
_rec_cb in libTwilioClient.a(audiotest.o)
_play_cb in libTwilioClient.a(audiotest.o)
"___udivmodsi4", referenced from:
_update_filter in libTwilioClient.a(resample.o)
ld: symbol(s) not found for architecture armv7
At this point I don't know how to resolve that
That function is a helper used by the compiler to implement a math operation that is more complex than a few CPU instructions. Is it possible you build your library with one compiler and are now linking in a different environment and a different compiler? If you built with gcc that function would be provided by libgcc.a.
Related
I have researched more into the problem and posted a more detailed question with my findings here: Rust, how to use global variable from DLL? C++ equivalent requires __declspec(dllimport)
Original question:
Summary:
When linking my project with MSVC 2019's link.exe, I am getting errors such as unresolved external symbol jl_module_type. These symbols are defined in a file julia.lib, which I have verified using dumpbin /exports julia.lib. This file is passed as an argument to link.exe, and yet, it still complains about unresolved symbols. It looks like all the symbols that failed to be linked are variables rather than functions.
More information:
julia.lib has been renamed from libjulia.dll.a, and it corresponds to another file libjulia.dll. They were built with Cygwin/MinGW, but AFAIK this should not affect things. The actual project this is being used in is written in Rust, so link.exe is being invoked automatically by Rust's cargo tool. It is configured to build my project as a DLL.
I am trying to build a Windows DLL from my Haskell code. The functions in this DLL are supposed to be called from a managed code in C#. And, atleast one of the function (defined in the c# code) is to be called from a function in this DLL.
At the risk of over explaining, here's a small diagram to depict what I want:
+----------------------+ +------------------------+
| Managed C# code | | Haskell code (in DLL) |
| | (1) | |
| fn_calling_hs() -----------------> fn_called_from_cs() |
| | | |
| | | |
| fn_called_from_hs() <--------------- fn_calling_cs() |
| | (2) | |
+----------------------+ +------------------------+
I managed to make the (1) work perfectly, i.e., a Haskell function in the DLL is called by C# code, with correct marshalling of structures and arrays, and the results from the function execution in Haskell is also correct. So far, so good.
The problem is with (2), i.e., a function from Haskell (in the DLL) calling a managed function defined in C#. The problem is in the build itself - I have not yet gone past that to actually check the results of (2).
As the fn_called_from_hs() in the c# managed code is defined in C#, I only have the function symbol "imported" in the Haskell code (in DLL):
foreign import ccall fn_called_from_hs :: IO CString
Now, when I build my Haskell project with stack, it builds the Haskell DLL without problems, but the build continues to also link "main.exe" - and this fails (obviously), because there is no function fn_called_from_hs() defined anywhere in the Haskell code (it is defined in c#).
Is there any way that I can stop stack from continuing to build main.exe after building HsDLL.dll? I am ok with HsDLL.dll having unresolved symbol (fn_called_from_hs()) because this symbol will be found by the runtime linker during the loading of this DLL by the managed C# code.
So far, I have tried these steps, but none of them helped:
Removed the "executables" and "test" from package.yaml
Added the GHC option: -no-hs-main in the package.yaml. The package.yaml
portion that contains building of HsDLL looks like this:
library:
source-dirs:
- src
- src/csrc
include-dirs: src/csrc
ghc-options:
- -shared
- -fno-shared-implib
- -no-hs-main
Completely removed the Main module (i.e., removed Main.hs that was automatically created by stack from the "app" folder)
I added the -dynamic flag in the ghc-options in the hopes that GHC will assume that the unresolved symbols will be defined elsewhere, but this gave other problems: GHC now complains that it needs "dyn" libraries of base, etc.
So, finally, I always end up with this:
PS C:\workspace\Haskell\hscs\src\csrc> stack build
hscs-0.1.0.0: configure (lib)
Configuring hscs-0.1.0.0...
hscs-0.1.0.0: build (lib)
Preprocessing library for hscs-0.1.0.0..
Building library for hscs-0.1.0.0..
Linking main.exe ...
.stack-work\dist\5c8418a7\build\HsLib.o:fake:(.text+0x541): undefined reference to `fn_called_from_hs'
collect2.exe: error: ld returned 1 exit status
`gcc.exe' failed in phase `Linker'. (Exit code: 1)
-- While building custom Setup.hs for package hscs-0.1.0.0 using:
C:\tools\HaskellStack\setup-exe-cache\x86_64-windows\Cabal-simple_Z6RU0evB_2.0.1.0_ghc-8.2.2.exe --builddir=.stack-work\dist\5c8418a7 build lib:hscs --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
So, my questions are:
(1) I have absolutely no idea how to stop linking "main.exe"! I know that the function fn_called_from_hs() is not defined within the HsDLL, but, as I said, I am ok because it is defined in the managed c# code. I just want main.exe not to be built.
OR
(2) Should I go ahead with adding -dynamic flag to GHC (keeping all the other flags as above)? In this case, how do I get stack to install the "dyn" libraries that GHC is complaining about?
Can somebody help me? Thanks in advance for your patience in reading this (rather) long question!
And so finally, I managed to solve this myself! After a week of struggle, that is. And any helpful comments to add it this answer is welcome.
I did this as follows:
In C# class DLL:
I had to find a way to "export" my function fn_called_from_hs() to unsafe native code. I found this is not really straight-forward, and there are really quite some amount of articles on the internet to explain how this is done. Everything amounts to actually disassembling the .NET DLL via the tool ildasm, and in the intermediate IL file generated, adding an ".export" prefix to the function that we want to export, and then again assembling the IL file back to the DLL form using ilasm.
I found all these steps are automated by the NUGetPackage Unmanaged Exports, so the first step is to install this package as a part of your .NET project, and then adding the DLLExport attribute to your function to be exported. Make sure you have RGiesecke.DllExport in your list of imports:
using RGiesecke.DllExport;
[DllExport("fn_called_from_hs", CallingConvention=CallingConvention.Cdecl)]
public static string FnCalledFromHs()
{
// Your function code here
}
As you can see, I have named the actual function as FnCalledFromHs() (in accordance with the naming convention in C#), but exported the same function as fn_called_from_hs (in accordance with the naming convention in Haskell). This way, when you look at the Haskell code, you will not see anything that looks out of place.
One of the most important steps for this to actually work is to make sure that the project in which you are exporting the function is made to target x64 or x86 - On default the projects target "Any CPU" - RGiesecke.DllExport does not work if the project targets "Any CPU".
Now build the project to get the csharp.dll which contains your exported fn_called_from_hs.
Before linking Haskell code
Mingw GCC (which ghc on Windows internally uses) can actually directly link with DLLs, provided they were created with gcc before. However, since we have created our C# DLL using the .NET compiler csc, we need to specifically create an import library that our Haskell can see.
We use two tools to our aid: gendef and dlltool, both of which are in the "mingw\bin" folder within your ghc installation (so, of course, you need to have this in your PATH env variable to access these tools).
Here's how I went about it:
Created a .def file which in-turn can be used for creating an import library:
gendef csharp.dll
Created an import library with dlltool:
dlltool -k -d csharp.def -l csharp.lib
Copied the above import lib to the same directory in which the DLL was present.
The last step (below) now will use this import library for actually linking with the csharp DLL.
Linking Haskell code with the above import library
This was a little trickier, and has possibly made me hit a bug in stack / GHC (not sure), but have already filed here.
I went about this as follows:
Added extra-lib-dirs in my stack.yaml, and added the directory in which the above import-lib was created:
extra-lib-dirs: ["<drive>:\\path\\to\\importlib"]
(Note that this could have also been added to your package.yaml under "libraries", but I chose to have it in my stack.yaml).
Added extra-libraries to my stack.yaml, under libraries.
extra-libraries: csharp
And, added also the options -l and -L to my ghc-options for linking my library. This is what I did to circumvent the (possible) bug that stack somehow is not passing the extra-lib-dirs and extra-libraries to ghc and ld during linking. So, my final "library" section in package.yaml looks like this (compare it to how it was before in my question above):
library:
source-dirs:
- src
- src/csrc
include-dirs: src/csrc
ghc-options:
- -shared
- -fno-shared-implib
- -lcslib
- -L<drive>:\\path\\to\\importlib
extra-libraries: csharp
Conclusion
With all this done, my Haskell code now simply builds well with the normal stack build command, without any "unreferenced symbols" error. On executing my Haskell code, I also checked that the c# function fn_called_from_hs was actually called, and the results got returned correctly.
Of course, there is more to this from the c# side: correct marshalling of parameters, etc., and I had to also work on those to get my result correct. The only place I can cover all of these nitty-gritties is in a blog :-)
Please feel free to cross-verify my solution, and also comment on any better way of doing this. This was the best way I could figure out after my struggles!
I've got a 3d party static library built with some older version of MSVC, and I successfully link it to my application in MSVC10 (VisualStudio2010). Now I upgraded to MSVC11, and I'm unable to link it:
2>LINK : fatal error C1047: The object or library file 'MyLib.lib' was
created with an older compiler than other objects; rebuild old objects
and libraries
I guess this happens because the lib was compiled with /GL option, so the object files don't really contain COFF, but some intermediate format.
I don't have the library source-code to re-compile, and I don't want to make a dll out of it to link dynamically.
Is there a way - maybe some undocumented trick - to "re-compile" these obj's to COFF and eventually link them to MSVC11 application?
Even if this was possible, you don't want to do this: linking object files that are built against different versions of the CRT usually ends in tears. More specifically, if two such object files both use the C++ Standard Library, it is all but certain that you will violate the One Definition Rule (ODR).
If you cannot rebuild the module using Visual C++ 2012, then you should encapsulate it within a dynamic library, built with Visual C++ 2010, and avoid using any C++ Standard Library types in the interface of that DLL.
I have been having this issue for a number of days now, and have been unable to make any headway on it.
I have a native Obj-C library that i am trying to bind using a MonoTouch binding project. The binding Dll is created, but when i import it to an app and try to compile I get a MT5202 Native linking failed error.
Reading the build output shows that the symbols for the iOS version i am compiling for are missing.
Undefined symbols for architecture armv7:
with the build output showing a number of linking issues (only a few shown)
"_CVPixelBufferGetPixelFormatType", referenced from:
-[DecodePickerController captureOutput:didOutputSampleBuffer:fromConnection:] in libQuickMarkSDK.a(DecodePickerController.o)
-[QMImageUtil saveToAlbum:] in libQuickMarkSDK.a(QMImageUtil.o)
"_CVPixelBufferGetPlaneCount", referenced from:
+[QMImageUtil imageBufferSave:f:] in libQuickMarkSDK.a(QMImageUtil.o)
+[QMImageUtil imageBuffer:zoom:w:h:f:] in libQuickMarkSDK.a(QMImageUtil.o)
"_CVPixelBufferGetWidth", referenced from:
-[DecodePickerController captureOutput:didOutputSampleBuffer:fromConnection:] in libQuickMarkSDK.a(DecodePickerController.o)
-[QMImageUtil saveToAlbum:] in libQuickMarkSDK.a(QMImageUtil.o)
"_CVPixelBufferGetWidthOfPlane", referenced from:
+[QMImageUtil imageBufferSave:f:] in libQuickMarkSDK.a(QMImageUtil.o)
"_CVPixelBufferLockBaseAddress", referenced from:
-[DecodePickerController captureOutput:didOutputSampleBuffer:fromConnection:] in libQuickMarkSDK.a(DecodePickerController.o)
"_OBJC_CLASS_$_AVCaptureDevice", referenced from:
objc-class-ref in libQuickMarkSDK.a(QuickMarkCameraUtil.o)
"_OBJC_CLASS_$_AVCaptureDeviceInput", referenced from:
objc-class-ref in libQuickMarkSDK.a(QuickMarkCameraUtil.o)
To begin with I thought it was just an error with the bindings. So I rebuilt the bindings. No joy. So to test a theory I tried to use the RedLaser mono bindings available from github. This also provided the same error. (if -unsafe is removed from the makefile).
the linkwith statement for the library I need to bind is
assembly: LinkWith ("libQuickMarkSDK.a", LinkTarget.ArmV7, ForceLoad = true, Frameworks = "AVFoundation CFNetwork CoreMedia CoreVideo libz.1.2.5.dylib MobileCoreServices QuartzCore Foundation SystemConfiguration")]
and the Monotouch addition flags being used is -cxx
I have read alot of the other issues but nothing has helped to solve the issue, any help would be great.
You did not state any version numbers (iOS, Xcode, MonoTouch...) so it's a bit hard to give a specific/definitive answer.
That situation can happens when you update a project to iOS6 / Xcode 4.5 where support for ARMv6 was removed. If your native libraries only included ARMv6 then they (the native library, not the binding project) will need to be recompiled for ARMv7 (since it's now a requirement).
To check this please try doing (include the full path to your native library):
file libQuickMarkSDK.a
That should tell you the architectures that your native library supports. Those needs to match the LinkTarget you provide in your binding project (otherwise you'll get errors from the native linker).
Did you try poupou's suggestion in his last comment? I had the same error when compiling for iPhone but not for Simulator. I found that it was a number of missing Frameworks in the LinkWith section. To work out which Frameworks were missing, I googled (for example) CVPixelBufferGetWidthOfPlane Framework.
Credit for this answer goes to cheeesus: MonoTouch Build: ld: symbol(s) not found for architecture armv7
By default, Visual Studio compiles a project to use the Multi Threaded DLL, found in the Visual Studio runtime. I want to compile my program using only /MT instead of /MD. Granted, that most systems already have this installed, and it's also available as a re-distributable.
When I change /MD to /MT, I get an error:
MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _free already defined in LIBCMT.lib(free.obj)
And four or five similar errors.
To try and fix this I removed LIBCMT.LIB from the default libraries.
I then get the error:
libcpmt.lib(_tolower.obj) : error LNK2019: unresolved external symbol __calloc_crt referenced in function __Getctype
Removing MSVCRTD.lib from the default list leads to similar errors?
It should be noted that:
-This is an OpenGL project, using the glfw library.
-I am using the SOIL image library by lonesock for texture loading.
Without any further precise information, I would say your first problem is that you're somehow mixing release and debug versions of libraries. MSVCRTD.lib is the debug version of MSVCRT.lib.
Either you have some debug settings hanging around in your own projects, or you're linking against debug versions of libraries you're using.
Never ever mix debug and release versions. If you're lucky you get an error like this. In some rare situations all magically seems to work until it doesn't.