I have read the documentation from Xamarin.
And this is my test class in Objective-C:
#import "XamarinBundleLib.h"
#implementation XamarinBundleLib
+(NSString *)testBinding{
return #"Hello Binding";
}
#end
It's very easy, just one method.
And this is my C# class:
namespace ResloveName
{
[BaseType (typeof (NSObject))]
public partial interface IXamarinBundleLib {
[Static,Export ("testBinding")]
NSString TestBinding {get;}
}
}
Then this is my AppDelegate code:
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
// Override point for customization after application launch.
// If not required for your application you can safely delete this method
string testStr = ResloveName.IXamarinBundleLib.TestBinding.ToString ();
System.Console.WriteLine ("testStr="+testStr);
return true;
}
When I run the application, I get this exception:
The TestBinding attributes is null.
I must be wrong somewhere, so how can I fix it?
I wrote a very detailed blog post about creating a static library from ObjC code last year that works on Xamarin.iOS binding projects and you can find it here (just in case :wink::wink:).
That being said if you already have a fat static library in your hands and it is already added into your Xamarin.iOS Binding Project as shown here:
The issue could be that your libxyz.linkwith.cs is missing some information, if it looks like this:
using ObjCRuntime;
[assembly: LinkWith ("libFoo.a", SmartLink = true, ForceLoad = true)]
it is definitely missing some important information about the architectures supported by your fat library (it is missing the second argument target), you can use the following command to retrieve what architectures your current static library supports
xcrun -sdk iphoneos lipo -info path/to/your/libFoo.a
and you should get something like this as output
Architectures in the fat file: Foo/libFoo.a are: i386 armv7 x86_64 arm64
So we know this static library supports i386 armv7 x86_64 arm64 and we should provide our LinkWith attribute the supported archs by providing the second argument target as follows:
using ObjCRuntime;
[assembly: LinkWith ("libFoo.a", LinkTarget.ArmV7 | LinkTarget.Arm64 | LinkTarget.Simulator | LinkTarget.Simulator64, SmartLink = true, ForceLoad = true)]
Also make sure that the first parameter of the LinkWith attribute matches your static library file name ("libFoo.a" in my case).
The other thing I would suggest double checking is that the Build Action of your static library (libFoo.a in my case) is correctly set to ObjcBindingNativeLibrary as show here:
Hope this helps!
Related
I have
installed Visual Studio Community 2019, version 16.3.3 (including "ASP.NET and Web development" and ".NET Core cross-platform development")
and have checked "Enable Navigation to decompiled Sources",
and created a new ASP.NET Core Web Application (.NET Core 3.0.0)
but when I then look at e.g. the decompiled source for any referenced class in the .NET framework e.g. System.Console or for Microsoft.AspNetCore.Builder (or almost any other type), all I can see for every method's body is throw null (I showed an extract below)
I have read this question (update: and the answer to the question it was a duplicate to), but there only one class had this problem (because it was added in an incremental update). For me, this problem applies to every class in the .NET framework. What am I doing wrong? Is this expected behaviour and I should use something like dotPeek?
Can I use a symbols server instead of decompiled sources?
(Forgive my ignorance, I'm really new to C#... and the .NET world)
region Assembly System.Console, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.0.0\ref\netcoreapp3.0\System.Console.dll
// Decompiled with ICSharpCode.Decompiler 4.0.0.4521
#endregion
using System.IO;
using System.Text;
namespace System
{
// Summary:
// ....
public static ConsoleColor BackgroundColor
{
get
{
throw null;
}
set
{
}
}
//
// Summary:
//...
public static int BufferHeight
{
get
{
throw null;
}
set
{
}
}
...
I've struggle several hours on that and I can't find what I'm doing wrong.
I created a new C# dll project, here is the content of the only class it contain:
using System;
using System.Runtime.InteropServices;
namespace PolygonSl {
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Config {
[ComVisible(true)]
public string GetCompany() {
return "POL";
}
}
}
I basically remove everything from it trying to make it work, the only reference is System.
I checked the Make assembly COM-Visible flag on the Assembly Information and my project is signed (seams required for codebase).
It compiling fine, after that, I called RegAsm.exe, giving it my dll, I added /codebase and /tlb, the command is successful.
When I go to my VBA project, I can add my new tlb file to the references, working fine. After, I can use it in my code, the autocomplete is working and I can compile with no errors.
Then, when I execute, I got this:
Run-time error '430':
Class does not support Automation or does not support expected interface
Here is my code sample in the VBA:
Private Sub Button1_Click()
'With CreateObject("PolygonSl.Config")
With New PolygonSl.Config
MessBox .GetCompany, MB_OK, "Test"
End With
End Sub
I tried late binding and my code is running fine with it but I'd like to be able to use the autocomplete.
Anyone have a suggestion on what I could try to make it work?
Edit (Adding some details on my environment)
I work on VS2008 for projects related to Dynamics SL (one of the Microsoft ERPs)
I'm on Windows Server 2008 R8 Standard, running from VMWare
Compiling on Framework 3.5, Release, x86, Dynamics SL client is 32 bits
I tried my dll on Dynamics but also on Excel to be sure that the problem was not Dynamics ;)
I think you need to define an interface to be able to see getcompany.
using System;
using System.Runtime.InteropServices;
namespace PolygonSl
{
[Guid("6DC1808F-81BA-4DE0-9F7C-42EA11621B7E")]
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IConfig
{
string GetCompany();
}
[Guid("434C844C-9FA2-4EC6-AB75-45D3013D75BE")]
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterface(ClassInterfaceType.None)]
public class Config : IConfig
{
public string GetCompany()
{
return "POL";
}
}
}
You can generate the interface automatically by placing the cursor in the class definition and using Edit.Refactor.ExtractInterface.
I'd have to admit that I'm at the absolute edge of my abilities here and the above is put together based on examples I've seen elsewhere.
Edit
The following test code works fine on my PC
Option Explicit
Sub polygontest()
Dim my_polygon As SOPolygon.Config
Set my_polygon = New SOPolygon.Config
Debug.Print my_polygon.GetCompany
End Sub
Where SOPolygon is the project name.
I've been following a set of tutorials (like this one) to create a simple COM server object.
Say I've got a simple hello world:
[ComVisible(true)]
[Guid("392930B3-9CD0-4247-8C69-83168D1C8F77")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("nathanr.HellowWorldCom")]
class HelloWorldCom : IHelloWorldCom
{
public int HelloWorld()
{
Console.WriteLine("Hello World!");
return 1;
}
}
With just as simple an interface:
[ComVisible(true)]
[Guid("C08205BE-1393-4070-AE57-FA47F0D653C3")]
interface IHelloWorldCom
{
[DispId(1)]
int HelloWorld();
}
And of course, can't forget the AssemblyInfo.cs file:
...
[assembly: ComVisible(true)]
[assembly: AssemblyKeyFile("HelloWorldCOM.snk")]
...
The problem is when I build the HelloWorldCom.dll and try to register it, regasm just sticks its tongue out at me:
RegAsm : warning RA00000 : No types were registered.
And just to cover my bases I cracked open Regedit and did a search for the ProgID. It wasn't there, which honestly wasn't a surprise.
Am I missing something obvious?
This whole test project is part of a larger (actually useful) set up which is also failing to register.
This will be a very long answer: add public
public class HelloWorldCom : IHelloWorldCom
There might be couple of issues:
You are selecting an incorrect .net framework. In my case, I was trying to register the dll with 2.0 framework, as opposed to 64 bit 4.0 framework
Your DLL is not publicly exposed.
Hope that resolves your issue.
Cheers
I have simple static lib in xcode with the only class
test.h:
#interface TestClass : NSObject {
NSString *SomeString;
}
#property(nonatomic, readwrite, copy) NSString *SomeString;
- (NSString *) getString;
- (int) getInt;
#end
test.m:
#implementation TestClass
#synthesize SomeString;
- (id)init
{
if ((self = [super init]) == nil)
return nil;
SomeString = #"test string value";
return self;
}
- (NSString *) getString {
return #"Lorem ipsum dolor sit amet";
}
- (int) getInt {
return 123;
}
#end
I've copied TstClass from the dll generated by btouch. if i'm using original dll's implementation:
[Register ("TestClass", true)]
public class TstClass : NSObject
variables Handle, ClassHandle etc are nulls, but app runs and returns nulls as a getInt, getString and SomeString. if I change definition to
[Register ("TestClass")]
public class TstClass : NSObject
inner variables are valid (meaning not null), but app crashes with no output when I'm trying to call a TstClass's function.
During my research I've found someone has fixed this by unchecking "thumb" option in XCode build setting, but I can not find anything that looks like thumb in xcode project. (just in case: XCode 4.2 build 4C199; and I'm using latest version of Monotouch)
How do I create static lib in xcode and use it with monotouch? what's wrong with my code?
and the last question: I have a .a and its .h files. is there an easier way to generate bindings from library and header files?
The easiest path to bind your library is to use the binding generator (this is the "btouch" tool which is part of MonoTouch):
A detailed document is here:
http://docs.xamarin.com/ios/advanced_topics/binding_objective-c_types
The reason your variables are null is that you did not properly initialize the library (ClassHandle is a virtual method that should return the return value from Class.GetHandle ("ClassName") in this case).
Use the following contract file with btouch to generate a proper binding:
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
namespace AlexD {
[BaseType (typeof (NSObject))]
interface TestClass {
[Export ("SomeString")] string SomeString { get; set; }
[Export ("getString")] string GetString ();
[Export ("getInt")] int GetInt ();
}
}
Save that into AlexD.cs and then run:
/Developer/MonoTouch/usr/bin/mtouch AlexD.cs
This will generate AlexD.dll that contains your binding to your native library. You can use this plus the proper set of command line arguments to mtouch to access your library.
You can also bundle your native library inside the DLL, to simplify distribution (single .dll will contain both the C# binding and the native library), for details on how to do this, see:
http://docs.xamarin.com/ios/advanced_topics/binding_objective-c_types#Linking_the_Dependencies
it took some time to figure out how to make it work.
Make sure lib and app target architectures are the same. (I had armv7 for lib and armv6 for app)
Make sure build targets are the same (was iOS device for lib and iOS simulator for app. iOS simulator target sets architecture to i386, which makes lib and app build incompatible)
for some reason additional mtouch arguments requires "-cxx -gcc_flags" and not just "-gcc_flags";
for some reason .a lib was not linked without "-force_load" argument;
add "-v -v -v" to additional mtouch arguments to see full build log. That helped a lot to find this solution.
Thumb instructions set must be disabled (fixed by adding User-defined project option GCC_THUMB_SUPPORT:NO)
that's it!
F# declared namespace is not available in the c# project or visible through the object browser.
I have built a normal F# library project, but even after i build the project and reference it to my C# project, I am unable to access the desired namespace.
I am also unable to see it in the object browser, i get an error telling me that it has not been built. I am running on the september release can someone point out my error ?
F# Version 1.9.6.0
(6) Edit : Referencing the dll directly has fixed my problem, referencing the project allows me to compile but the intellisence does not work. When the dll is directly referenced the intellisence works perfectly.
This is the code found in the .fs file
#light
namespace Soilsiu.Core
module public Process =
open System.Xml.Linq
let private xname (tag:string) = XName.Get(tag)
let private tagUrl (tag:XElement) = let attribute = tag.Attribute(xname "href")
attribute.Value
let Bookmarks(xmlFile:string) =
let xml = XDocument.Load(xmlFile)
xml.Elements <| xname "A" |> Seq.map(tagUrl)
let PrintBookmarks (xmlFile:string) =
let list = Bookmarks(xmlFile)
list |> Seq.iter(fun u -> printfn "%s" u)
(5) Edit : Could ReSharper 4.0 be the problem?
(4) Edit : When i say the Object browser is unable to read the resulting assembly, i mean that when I try to open the assembly in the object browser i get an error telling me the project has not yet been built. yet again i can read the assembly using reflector.
(3) Edit : Reflector can Disassemble the dll but the Object Browser is unable to read it.
(2) Edit : I have Upgraded my F# version to 1.9.6.2 and still the same consequence
(1) Edit : I was able to Disassemble the dll to C# I get : (Everything seems to be fine here)
namespace Soilsiu.Core
{
[CompilationMapping(7)]
public static class Crawler
[CompilationMapping(7)]
public static class Process
}
[CompilationMapping(7)]
public static class Process
{
// Methods
static Process();
public static IEnumerable<string> Bookmarks(string xmlFile);
public static void PrintBookmarks(string xmlFile);
internal static string tagUrl(XElement tag);
internal static XName xname(string tag);
// Nested Types
[Serializable]
internal class clo#13 : FastFunc<XElement, string>
{
// Methods
public clo#13();
public override string Invoke(XElement tag#9);
}
[Serializable]
internal class clo#17 : FastFunc<string, Unit>
{
// Methods
public clo#17();
public override Unit Invoke(string u);
}
}
What if you reference the produced DLL directly (i.e., not via a project reference, but via a file reference)?
Maybe IntelliSense is just messed up? What compiler error do you get when you try to use it in C#? When you say "the object browser is unable to read it" what does that mean?
For what it's worth, I added this to a F# library project, referenced it (project) from a C# console app, and was able to use it. IntelliSense did not work at first though. (Had to rebuild.)
If you can make a solid repro, I'd suggest emailing it to F# bugs alias (fsbugs).
I tried the same thing. It looks as if Visual Studio and Resharper 4.0 doesn't understand F# for some reason. If you ignore the sea of red text and the lack of intellisense, it will compile fine.
Try
Make sure that C# project is targeted FULL .NET (NOT Client Profile).
Add references to assemblies into C# project which are used by F# project.