MonoTouch binding to Pony Debugger - PDDebugger.DefaultInstance always null - xamarin.ios

I am writing a binding for pony Debugger, which should be pretty simple right?
Pony is accessed through a class member "defaultInstance"
#interface PDDebugger : NSObject
+ (PDDebugger *)defaultInstance;
Which I have implemented like this:
[assembly: LinkWith ("libPonyDebugger.a", LinkTarget.Simulator, ForceLoad = true)]
namespace PonyDebugger
{
[BaseType (typeof (NSObject))]
interface PDDebugger
{
[Static] [Export ("defaultInstance")]
PDDebugger DefaultInstance { get; }
[Export ("enableViewHierarchyDebugging")]
PDDebugger EnableViewHierarchyDebugging();
}
}
I can compile the binding fine - but when I call "PDDebugger.DefaultInstance" I just get back null. What am I missing?
How can I even be sure that the message is being passed to the underlying ObjC object?
Thanks!
[EDIT]
I have updated my bindings to:
using System;
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
** libPonyDebugger.linkwith.cs **
[assembly: LinkWith ("libPonyDebugger.a", LinkTarget.Simulator, ForceLoad = true,
Frameworks = "Security CFNetwork Foundation CoreGraphics UIKit CoreData", LinkerFlags = "-ObjC -licucore")]
namespace PonyDebugger
{
[BaseType (typeof (NSObject), Name="PDDebugger")]//, DisableDefaultCtor]
interface PDDebugger
{
//+ (PDDebugger *)defaultInstance;
[Static, Export ("defaultInstance")]
PDDebugger DefaultInstance();
[Export ("enableViewHierarchyDebugging")]
PDDebugger EnableViewHierarchyDebugging();
}
}
** libSocketRocket.linkwith.cs **
using System;
using MonoTouch.ObjCRuntime;
[assembly: LinkWith ("libSocketRocket.a", LinkTarget.ArmV7 | LinkTarget.Simulator,
Frameworks = "Security CFNetwork Foundation CoreGraphics UIKit CoreData", ForceLoad = true, LinkerFlags = "-ObjC -licucore")]
And it all btouches/compiles to native and runs - but PDDebugger.DefaultInstance() still returns null.

If you are getting null, it probably means that the native library isn't being linked in correctly.
Are you running on Simulator or Device? How did you compile the binding? Are you sure that the native library has support for the architecture you are testing on?

I did a quick test to bind PonyDebugger a while ago. The bindings were fine - but it did not work, because of method swizzling IIRC.
From a quick review your linkwith.cs looks incomplete. Mine was:
[assembly: LinkWith ("libPonyDebugger.a", LinkTarget.ArmV7 | LinkTarget.Simulator,
ForceLoad = true,
Frameworks = "Security CFNetwork CoreData",
LinkerFlags = "-ObjC -licucore" )]
I also needed to include libSocketRocket.a, simpler since I added the framework and flags to pony.
[assembly: LinkWith ("libSocketRocket.a", LinkTarget.ArmV7 | LinkTarget.Simulator,
ForceLoad = true)]
That should give you a non-null instance of PDDebugger - but you'll need more work to get actual result out of it. Sadly I lacked time to dig it further, but let us know when you figure out the rest :-)

Related

Expose types from embedded interop type to other assemblies

I have an ATL COM library that defines an enum and an interface in MIDL like:
[uuid(65785D49-574A-4B1B-95F1-B9C7F283364A)]
typedef enum Options
{
Option1,
Option2
} Options;
[
object,
uuid(2E3D1B1A-DF95-434F-836B-73FF1245B608),
oleautomation,
nonextensible,
pointer_default(unique)
]
interface IExample : IUnknown
{
HRESULT Test([in] Options option, [out, retval] BSTR* str);
};
I then create a managed assembly and reference the TLB, which creates a PIA and embeds the types (Embed Interop Types = true) into the managed assembly.
In the managed assembly, I now create a class that implements the interface:
public class Example : IExample
{
public string Test(Options option)
{
return option.ToString();
}
}
Now I would like to create a third assembly that references the managed assembly and creates the object and call into it, but it doesn't let me since Options is an unreferenced type (requires me to include the PIA generated from the typelib):
public class Equivalence
{
public void UseTest()
{
Example e = new Example();
e.Test(Options.Option1); // recognizes that it requires an ExampleLib.Options parameter, but that type isn't available
}
}
Using reflector, I can see it inside the managed assembly, but it isn't viewable by object browser:
namespace ExampleLib
{
[ComImport, CompilerGenerated, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("2E3D1B1A-DF95-434F-836B-73FF1245B608"), TypeIdentifier]
public interface IExample
[Guid("65785D49-574A-4B1B-95F1-B9C7F283364A"), CompilerGenerated, TypeIdentifier("15a6cf97-c415-4866-bdfb-7da65edb1faa", "ExampleLib.Options")]
public enum Options
}
My managed assembly is itself a library intended to be distributed as an API, and I would like to expose this enumeration and interface so that it can be used by outside parties without having to deliver the PIA generated from the typelib of the ATL COM library. Is it possible?
Apparently this cannot be done. One of the errors (CS1748) pointed me to this post which says the PIA must be linked in by both assemblies.

The name 'PropertySupport' does not exist in the current context

I would like to create a base class for observableObject generic enough for an observable object to derive from, but I hit some technical issue. This is an extract of the class. It is an abstract that implements interface INotifyPropertyChanged. But when I tried to use PropertySupport.ExtractPropertyName, I got compiler error saying 'PropertySupport' not exist in the current context. I am using VS2002. My intention was to create a library to host a small "framework" of my own and use it for different projects. Could anyone more well versed in the reflection point out what was wrong in my code to cause the compiler error?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace MyFramework
{
[Serializable]
public abstract class ObservableObject: INotifyPropertyChanged
{
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
var handler = this.PropertyChanged;
if (handler!=null)
{
handler(this, e);
}
}
protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
this.RaisePropertyChanged(propertyName);
}
protected void RaisePropertyChanged(String propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
}
}
The error you are getting usually refers to a missing using directive or missing reference.
Looking at MSDN for the function you are trying to use it looks like you are missing the using directive Prism.ViewModel
using Microsoft.Practices.Prism.ViewModel;
If this doesn't fix your problem then you need to add a reference to the correct dll
Microsoft.Practices.Prism.Composition.dll
I've never used Prism but after copying your class, adding the correct reference & using directive it built ok.

How to unregister a class in mono touch

In monotouch using c# I have used [Register("CpyRightCusTabVwCell")] above the afore mentioned class. Now I want to un-register that class. How do I do that in monotouch using C#?
using System;
using MonoTouch;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Runtime.CompilerServices;
using System.Net.Mime;
using NUnitLite.Runner;
namespace egUniSBPersHlthCareManager
{
[Register("CpyRightCusTabVwCell")]
public partial class CpyRightCusTabVwCell : UITableViewCell
{
public CpyRightCusTabVwCell(IntPtr handel):base (handel)
{
}
public CpyRightCusTabVwCell ()
{
}
}
}
You can't.
Class registration is for life (of the process).

MonoTouch binding issue of inheriting abstract member

I am working on MonoTouch binding of an Objective-C application. I referred iOS Binding Walkthrough.
I have generated libraries for i386, ARM and then a universal library. Further, I created a MonoTouch Binding Project. I have generated ApiDefinition using Sharpie and added the universal library generated earlier. Now when I build this project I am getting the following error.
ADClusterAnnotation.g.cs(86,86): Error CS0533: AnnotationClusterMap.ADClusterAnnotation.Coordinate' hides inherited abstract member MonoTouch.MapKit.MKAnnotation.Coordinate' (CS0533)
Here is the code snippet of ADClusterAnnotation:
File ADClusterannotation.h
#interface ADClusterAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D _coordinates;
}
#property (nonatomic) CLLocationCoordinate2D coordinate;
#end
File ADClusterAnnotation.m
#synthesize coordinate = _coordinates;
Here is the code snippet from ApiDefinition
[BaseType (typeof (MKAnnotation))]
public partial interface ADClusterAnnotation {
[Export ("coordinate")]
CLLocationCoordinate2D Coordinate { get; set; }
}
So I think we need to change something in ApiDefinition. I tried removing Coordinate from ADClusterAnnotation in the API definition, but then it gives an error that it implements an abstract member. What am I missing with regard to Monotouch binding?
Overriding an abstract member require c# new or override
You can get that to be generated by changing your ApiDefinition to:
[BaseType (typeof (MKAnnotation))]
public partial interface ADClusterAnnotation {
[Export ("coordinate")]
[New]
CLLocationCoordinate2D Coordinate { get; set; }
}

Create Managed Object From Unmanaged Class Function

I am trying to create a Managed C++/CLI object in unmanaged code.
Is this possible?
If so, am I doing it right? see code below
#include <vcclr.h>
#include <ManagedClass.h>
// compiled with /clr
namespace X
{
class UnmanagedClass
{
UnmanagedClass(){}
~UnmanagedClass(){}
gcroot<Y::ManagedClass^> m_guiControl;
void functionA()
{
m_guiControl = new gcroot<Y::ManagedClass^>;
}
}
}
// compiled into Managed dll with /clr
// in file ManagedClass.h in a separate project
using namespace System::ComponentModel;
// more usings here ..etc
namespace Y {
public ref class ManagedClass : public System::Windows::Forms::UserControl
{
// implementation here
}
}
When I compile the UnmanagedClass source file, I keep getting a whole lot of errors with the first one being error C2039: 'ComponentModel' : is not a member of 'System'. How come it is not recognising ComponentModel?
I thought this was suppose to be IJW (it just works) ;-)
Here's an example for a wrapper:
class UnmanagedClass
{
gcroot<ManagedClass^> m_managed;
public:
UnmanagedClass()
{
m_managed = gcnew ManagedClass();
}
};
Look here:
C++/CLI - Managed class to C# events
wrapper to c++/cli
Edit:
When you get an error on a using statement, and you know it's supposed to exist, It's usually because that dll isn't referenced.
Go to the projects references, choose add reference.
You can add .Net assemblies in the .Net tab. Find the one you need and add it.

Resources