I'm trying to use SWIG to wrap unmanaged C++ into my Xamarin.iOS project. I've successfully wrapped it into a C# project following this tutorial: https://stackoverflow.com/a/9816646/2494785
Once I try to incorporate MonoTouch, I always get run-time errors as soon as a call is made involving my C++ code.
I understand minor tweaks need to be made when using SWIG with Monotouch, but I must be missing something. I was following Stephane's blog http://blog.reblochon.org/2013/01/c-bindings-for-monotouch-using-swig.html#more as a reference.
Differences between my C#/Monotouch projects:
Monotouch
- swig -csharp -c++ -outdir myPath -dllimport __Internal cpp_file.i
I then run this ruby script (created by James Moore) on my cppPINVOKE.cs
ARGF.each do |l| case l when /public delegate void Exception(Argument)?Delegate/ puts " [MonoTouch.MonoNativeFunctionWrapper]", l when /static void SetPendingArgument(Null|OutOfRange)?Exception/ puts " [MonoTouch.MonoPInvokeCallback (typeof (ExceptionArgumentDelegate))]", l when /static void SetPending.*Exception/ puts " [MonoTouch.MonoPInvokeCallback (typeof (ExceptionDelegate))]", l when /static string CreateString/ puts " [MonoTouch.MonoPInvokeCallback (typeof (SWIGStringDelegate))]", l else puts l end end
C#
- swig -csharp -c++ -outdir myPath cpp_file.i
Here's the exception I get when I try to run my project:
Unhandled Exception:
System.TypeInitializationException: An exception was thrown by the type initializer for cppPINVOKE
Unhandled Exception: System.TypeInitializationException: An exception was thrown by the type initializer for cppPINVOKE ---> System.TypeInitializationException: An exception was thrown by the type initializer for SWIGExceptionHelper ---> System.EntryPointNotFoundException: SWIGRegisterExceptionCallbacks_cpp at (wrapper managed-to-native) cppPINVOKE/SWIGExceptionHelper:SWIGRegisterExceptionCallbacks_cpp (cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate,cppPINVOKE/SWIGExceptionHelper/ExceptionDelegate) at cppPINVOKE+SWIGExceptionHelper..cctor () [0x000ef] in c:\Users\joshs\ Documents\Visual Studio 2012\Projects\StackOverFlowSwigWithXamarin\StackOverFlowSwigWithXamarin\Generated\cppPINVOKE2.cs:121 --- End of inner exception stack trace --- at cppPINVOKE..cctor () [0x00000] in c:\Users\joshs\Documents\Visual Studio 2012\Projects\StackOverFlowSwigWithXamarin\StackOverFlowSwigWithXamarin\Generated\cppPINVOKE2.cs:141 --- End of inner exception stack trace --- at cpp_file..ctor () [0x00000] in c:\Users\joshs\Documents\Visual Studio 2012\Projects\StackOverFlowSwigWithXamarin\StackOverFlowSwigWithXamarin\Generated\cpp_file.cs:43 at StackOverFlowSwigWithXamarin.MyViewController.b__0 (System.Object sender, System.EventArgs e) [0x00001] in c:\Users\joshs\Documents\Visual Studio 2012\Projects\StackOverFlowSwigWithXamarin\StackOverFlowSwigWithXamarin\MyViewController.cs:38 at MonoTouch.UIKit.UIControlEventProxy.Activated () [0x00000] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIControl.cs:30 at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication: UIApplicationMain (int,string[],intptr,intptr) at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
at StackOverFlowSwigWithXamarin.Application.Main (System.String[] args) [0x00001] in c:\Users\joshs\Documents\Visual Studio 2012\Projects\StackOverFlowSwigWithXamarin\StackOverFlowSwigWithXamarin\Main.cs:17 2013-10-31 14:45:48.261 StackOverFlowSwigWithXamarin[13645:21e03] Unhandled managed exception: An exception was thrown by the type initializer for cppPINVOKE (System.TypeInitializationException) at cpp_file..ctor () [0x00000] in c:\Users\joshs\Documents\Visual Studio 2012\Projects\StackOverFlowSwigWithXamarin\StackOverFlowSwigWithXamarin\Generated\cpp_file.cs:43 at StackOverFlowSwigWithXamarin.MyViewController.b__0 (System.Object sender, System.EventArgs e) [0x00001] in c:\Users\joshs\Documents\Visual Studio 2012\Projects\StackOverFlowSwigWithXamarin\StackOverFlowSwigWithXamarin\MyViewController.cs:38 at MonoTouch.UIKit.UIControlEventProxy.Activated () [0x00000] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIControl.cs:30 at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr) at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/ MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38 at StackOverFlowSwigWithXamarin.Application.Main (System.String[] args) [0x00001] in c:\Users\joshs\Documents\Visual Studio 2012\Projects\StackOverFlowSwigWithXamarin\StackOverFlowSwigWithXamarin\Main.cs:17 mono-rt: Stacktrace:
So why am I getting this exception and how can I fix it?
Edit (2013-11-1) My (more/less) complete setup:
VS2012 StackOverFlowSwigWithXamarin.sln contains two projects
- cpp.vcxproj (C++ project)
- StackOverFlowSwigWithXamarin.csproj (Xamarin iOS project created from VS (i.e. No .xibs))
- The Xamarin project was made in VS2012 File -> New -> Project... -> Visual C# -> iOS -> iPad -> HelloWorld Application
cpp Project
cpp_file.h
#pragma once
#ifdef cpp_EXPORTS
#define cpp_API __declspec(dllexport)
#else
#define cpp_API __declspec(dllimport)
#endif
class cpp_API cpp_file
{
public:
cpp_file(void);
~cpp_file(void);
int times2(int arg);
};
cpp_file.cpp
#include "cpp_file.h"
cpp_file::cpp_file(void)
{
}
cpp_file::~cpp_file(void)
{
}
int cpp_file::times2(int arg)
{
return arg * 2;
}
cpp_file.i
%module cpp
%{
#include "cpp_file.h"
%}
%include <windows.i>
%include "cpp_file.h"
The cpp_file.i file is set as a custom build option within VS2012. It runs the command
swig -csharp -c++ -outdir "$(SolutionDir)StackOverFlowSwigWithXamarin\Generated" cpp_file.i
The outputs from the custom build tool is specified as:
cpp_file_wrap.cxx
....but I never use this file, I have no idea what it's there for?
Building my cpp Project produces the following files:
- cpp_file_wrap.cxx
- cpp.cs
- cpp_file.cs
- cppPINVOKE.cs
Afterwards, I run my ruby script to create a new file I named cppPINVOKE2.cs
StackOverFlowSwigWithXamarin Project
AssemblyInfo.cs
I noticed Stephane mentioned to add [assembly: LinkWith(....)
, but I did not, because I never created a .lib/.a
The autogenerated are added to my project:
- cpp.cs
- cpp_file.cs
- cppPINVOKE2.cs (from the ruby script, mentioned above)
AppDelegate.cs, Main.cs
I made no changes to the default VS2012 -> iPad HelloWorldApplication
MyViewController.cs
I added one line to the default HelloWorldApplication. When the user presses the button on the screen, it tries to instantiate a cpp_file()
.
My Concerns
- I never touch the .cxx file. Why is it there? (Maybe that's part of my problem)
- From Stephane's blog, he recommends to add
[assembly: Linkwith(...)]
to my assemblyInfo.cs. I never created a library, should I have? If so, of what?