Python C# interop - c#

In an assembly Test.Dll I have a C# class:
public class MyClass : IDisposable
{
int _TheInt;
public MyClass (int i) {_TheInt = i;}
public int GetInt() { return _TheInt;}
}
and a function:
public int MyFunc(MyClass myObject) { return myObject.GetInt(); }
How, in an ironPython script, create an object of type MyClass and call MyFunc with this object?
I can do the first step but as I am not an expert in neither C# and Python I failed for the second step.
Any help would be highly appreciated.

First, you need to import dll:
import clr
clr.AddReferenceToFileAndPath(r"/path/to/Test.dll")
then after reference was added, you can import your C# namespace or class, and create the object:
import MyNameSpace.MyClass # namespace name class from C# DLL
obj = MyClass(1)
# Now you have an object, let's call the methods:
myIntValue = obj.GetInt()
Then, if you want to call MyFunc, instead of direct call of GetInt(), you need to make it static (since it accepts object as argument
//Put that inside MyClass declaration, cause global functions are not allowed by C#
public static int MyFunc(MyClass myObject) { return myObject.GetInt(); }
And call it on python's side:
result = MyClass.MyFunc(obj)

Related

Object from class library not contains methods

Trying to build and use class library in C#.
Creating class library:
File->New Project->Windows->Classic Desktop->Class Library
Code:
namespace ClassLibrary2
{
public class Class1
{
public static long Add(long i, long j)
{
return (i + j);
}
}
}
Trying to consume it from console application:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ClassLibrary2.Class1 c = new Class1();
c. //no Add function
}
}
}
But c object not contains Add function. Why? How how to fix it?
Add is a static method. You can't call static methods "via" instances in C#. That has nothing to do with it being in a different library.
You can call the method as:
long result = ClassLibrary2.Class1.Add(10, 20);
or if you actually have a using directive for ClassLibrary2 (it's unclear from the question):
long result = Class1.Add(10L, 20L);
Alternatively, change the method to be an instance method, if that's what you wanted - at which point you'd be able to call c.Add(10L, 20L).
You declared Class1 as static, then, you don't need an instance to use it.
ClassLibrary2.Add(1, 1);
Add in static method. You must call it like static method:
Class1.Add(1,2);
If You intent to make it Instance specific remove the static
namespace ClassLibrary2
{
public class Class1
{
public long Add(long i, long j)
{
return (i + j);
}
}
}

Using C# dll functions in matlab code

I have a C# project, and I want to use the function of my project in matlab.
I've added
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
befor every classes in my project and make the out put type class library.
but when I use of dll in matlab,
temp = NET.addAssembly('../../foo')
and then foo.Classes, there is no class!
what should i do?! plz help me :)
Sample regarding above comment
To use a class from a .NET assembly using NET.addAssembly(...), there is no need to make the class COM Visible but the class, as well as the methods you want to access to, have to be public.
.NET code
namespace foo
{
public class SampleClass
{
// Constructor
public SampleClass() { }
// Static example
public static string StaticMethod() { return "Hello from static method."; }
// Instance example
public string InstanceMethod() { return "Hello from instance method."; }
}
}
Usage from Matlab
% Loading the .NET assembly
NET.addAssembly('..\..\Foo.dll');
% Call of a static method
foo.SampleClass.StaticMethod()
% Call of an instance method
instance = foo.SampleClass();
instance.InstanceMethod();

How to pass a JNI C# class into Java or handle this situation?

I'm trying to call a Java method from C#, it's called like this from java:
EgamePay.pay(thisActivity, payAlias, new EgamePayListener() {
#Override
public void paySuccess(String alias) {
}
#Override
public void payFailed(String alias, int errorInt) {
}
#Override
public void payCancel(String alias) {
}
});
The first two parameters are ok, but how do I pass the EgamePayListner through in C#? Simply creating a C# class with the same functions won't work...
Here's what I'm doing currently:
using (AndroidJavaClass jc = new AndroidJavaClass("cn.egame.terminal.smspay.EgamePay"))
{
System.IntPtr cls_Activity = AndroidJNI.FindClass("com/unity3d/player/UnityPlayer");
System.IntPtr fid_Activity = AndroidJNI.GetStaticFieldID(cls_Activity, "currentActivity", "Landroid/app/Activity;");
object[] p = { fid_Activity, "payAlias", new EgamePayListener() };
jc.CallStatic("pay", p);
}
..
class EgamePayListener
{
public void paySucess(string alias)
{
}
public void payFailed(string alians, int errorInt)
{
}
public void payCancel(string alias)
{
}
}
Obviously that's wrong, how can I handle this situation so that I can get notified back in C# land when those functions are fired?
You can link these projects together in VS201X via references. From here, you should be able to fill in the other layers(JNI/Java), and then start passing your pointers(as a long) around the system and invoking your functions.
C# Layer
Program.cs
namespace CSharpLayer
{
class Program : CLILayer.CLIObject
{
static void Main(string[] args)
{
Program p = new Program();
p.invokeJava();
}
public void invokeJava()
{
//Call into CLI layer function to loadJVM, call Java code, etc
loadJava();
}
public override void callback(string data)
{
//This will be called from the CLI Layer.
}
}
}
C++/CLI Layer - DLL C++ project w/ CLR support(/clr)
CLIObject.h
#pragma once
namespace CLILayer
{
public ref class CLIObject
{
public:
CLIObject();
~CLIObject();
void loadJava(System::String^ jvm, System::String^ classpath);
virtual void callback(System::String^ data) = 0;
};
}
CLIObject.cpp
#include "CLIObject.h"
#include <string>
#include <msclr/marshal_cppstd.h>
#include <msclr/marshal.h>
using namespace msclr::interop;
using namespace CLILayer;
CLIObject::CLIObject()
{
}
CLIObject::~CLIObject()
{
}
CLIObject::loadJava(System::String^ jvmLocaion, System::String^ classpath)
{
std::string _jvmLoc = marshal_as<std::string>(jvmLocation);
std::string _classpath = marshal_as<std::string>(classpath);
}
if you are in a context of Unity3D, a better way to interact from Java native code to Unity3D C# script would be the calling the UnitySendMessage method. You can call this method in you Java code, and a message will be sent to C#, so you can get a specified method executed in C#.
You could add a gameObject in your Unity scene and create a MonoBehavior script which contains these three methods (paySucess(string message), payFailed(string message) and payCancel(message)). Then attach the new created script to the gameObject (let us assume the name of this gameObject to be "PayListener") and make sure the gameObject existing in your scene when the Java code be executed (you can call DontDestroyOnLoad on the gameObject in Awake, for example).
Then, in your Java code, just write like these:
EgamePay.pay(thisActivity, payAlias, new EgamePayListener() {
#Override
public void paySuccess(String alias) {
com.unity3d.player.UnityPlayer.UnitySendMessage("PayListener","paySuccess", alias);
}
#Override
public void payFailed(String alias, int errorInt) {
com.unity3d.player.UnityPlayer.UnitySendMessage("PayListener","payFailed", alias + "#" + errorInt);
}
#Override
public void payCancel(String alias) {
com.unity3d.player.UnityPlayer.UnitySendMessage("PayListener","payCancel", alias);
}
});
It would prevent the java file to build successfully without the com.unity3d.player.UnityPlayer class. You could find the /Applications/Unity/Unity.app/Contents/PlaybackEngines/AndroidPlayer/bin/classes.jar file and add it as a dependency library for your java project. Then you can build, generate and use the new jar file without error.
Because of the UnitySendMessage method can only take 1 parameter, so you might have to connect the payFailed result alias and errorInt by a strategy, and parse it back in Unity C# side.
By using the new built jar file and load it as a AndroidJavaClass or AndroidJavaObject, the corresponding method in the PayListener script should be called when the one in Java is get called.
For documentation of the Android plugin with UnitySendMessage, you can visit the official guide of how to implement a Android JNI plugin here, in the example 3.
Here is JNI Field Descriptor
JavaLanguage Type
--------------------------------
Z boolean
B byte
C char
S short
I int
J long
F float
D double
Ljava/lang/String; string
[Ljava/lang/Object; object[]
Method descriptors make use of the fields descriptors and describe the structure of a Java method. There are no spaces between the field descriptors in a method descriptor.
Apart from the void return type which is denoted by V, all other return types use the field descriptor. The table below describes the Java method declaration and the corresponding JNI descriptor. The JNI method descriptor is used when calling a Java method from C# via JNI.
Java Method Declaration JNI Method Descriptor
----------------------------------------------------
String foo(); "()Ljava/lang/String;"
Void bar(int I, bool b); (IZ)V
The first thing that needs to be done is to create a dictionary object that will contain all of the parameters to pass to the Java Virtual Machine. In the example below, I am doing the minimum of setting the class path that will tell the JVM where to look for the classes and packages.
private Dictionary<string, string> jvmParameters = new Dictionary<string, string>();
jvmParameters.Add("-Djava.class.path", Location of the java class);
Once the JVM parameters have been assigned to the dictionary object, an instance of JavaNativeInterface can be created. Once created, the method LoadJVM needs to be called with the JVM parameters, and this will then load up the Java Virtual Machine. Once loaded, the user calls the method to instantiate the Java object (note that the use of the method InstantiateJavaObject is optional as the user may just want to call a static method, in which case, this method does not need to be called; however, it will not case any harm).
Java = new JavaNativeInterface();
Java.LoadVM(jvmParameters, false);
Java.InstantiateJavaObject(Name of the java class excluding the extension);
Once the JVM has been loaded and a class instantiated, the user may call any method they wish. First create an object list that will contain all of the parameters to pass into the Java method. As it is an object list, it can hold parameters of different types as everything inherits from an object.
List<object> olParameters = new List<object>();
olParameters.Add(Value of the parameter to be passed to the java method);
Next, simply call the generic method CallMethod passing in the return type of the Java method as the template type. In the example below, I am calling CallMethod which means that the return type of my Java method that I want to call is a string.
Next, pass in the name of the Java method to call and the method descriptor (see above); finally, pass in the list of all of the parameters. (Note: If no parameters are required, then pass in an empty list.)
Java.CallMethod<string>("AddTwoNumbers", "(IILjava/lang/String;)I", olParameters);
Well, I guess that wraps it all up, but remember that there is so much more you can do with JNI. The test application was just a quick and dirty way to demonstrate the basics of the JNI component. For a full understanding of JNI.
Either you can get more on this link
Have a look at http://jni4net.sourceforge.net/. I have successfully used it to communicate between CLR and JVM. Java application example that calls .NET classes can be found here. Events (bound to java listener interfaces) are supported too.
I ended up solving this problem myself, the other answers posted here while good unfortunately did not address the fact the problem I was facing was in Unity.
The way I solved it was by writing a custom listener class in Java with a 'GetResult' function that returned a string explaining what the outcome was (i.e. which function was called and with what result) and a get function for the result which C# called through AndroidJNI.
After making the purchase call it was a matter of calling the get function from C# until I had a result.
Sounds like a mess. What are you trying to accomplish exactly and why? Why not just run the JVM separately and CLR separately, interface over REST calls or something similar?

custom class library as an array C#

I'm working with a class library in C# with its own methods and I want to create an array from this library, but I when call it in the main program I cant see its methods.
public class ClassLibrary1
{
public int num;
public ClassLibrary1 ()
{
}
public void Readdata()
{
Console.Write("write a number ");
num = int.Parse(Console.ReadLine());
}
}
program.cs :
ClassLibrary1[] arraynumbers = new ClassLibrary1[5];
arraynumbers.Readdata();
And I can't use Readdata().
Can anyone help me?
If you want to call methods in your class, you'll have to create at least one instance. As it is, all you've done is create an array of null references, and then attempt to call your method on the array. Here's one way you could do it.
ClassLibrary1[] arraynumbers = new ClassLibrary1[5];
for(int i = 0; i < 5; i++)
{
arraynumbers[i] = new ClassLibrary1();
}
arraynumbers[0].Readdata();
You can't use Readdata the way you've put it because ClassLibrary1[] is an ARRAY object, not a ClassLibrary1 object, in which your method is defined.
You'd have to do something like this instead:
arraynumbers[0].Readdata();
Readdata() is a method of the ClassLibrary1 instance, not the array that holds ClassLibrary1 instances.
Methods that are defined on a class may not be called on a collection of that class. If you want to use a method on a collection, consider making an extension method:
public static class ClassLibrary1Extensions
{
public static Readdata(this ClassLibrary[] value)
{
...
}
}
The "this" keyword in the first parameter allows you to "pretend" this method is on a type of "ClassLibrary1[]" or array. I.e. extending that type.

C# equivalent of VB Public Module, With too please

I'm converting a VB.net library to C# and having trouble finding the C# equivalent to a VB.Net Public Module.
In the same VB class is a With block. Any idea what the equivalent might be for that as well.
TIA
Steve Campos
Unfortunately there is no equivalent of a VB.Net module in C#. The closest thing is a static class. Both define a object which cannot have instance members but they have different semantics. The largest being that for VB.Net if a Module is in scope it's members can be accessed without qualification
Module Example
Public Function Sum(x as Integer, y As Integer) As Integer
return x + y
End Function
End Module
Class C1
Sub Method1()
Dim x = Sum(13,42)
End Sub
Class
C# does not have this feature and requires qualified access for static class members.
There are a couple of other smaller differences
Module members are implicitly shared while static class members require explicit static qualifiers
Some minor trivia in the structure of the generated types
There is no With equivalent.
Depending on version, you can do:
var myCommand = new SqlCommand(SpMainInsert, myConnection) {
CommandType = System.Data.CommandType.StoredProcedure
};
Module Definition
This is the correct definition based on the default declaration when creating a Module (Module template item) in a VB.NET Project. The private constructor is part of the declaration, regardless if it is required or not. This C# "Module Definition" is taken from a Microsoft resource many years back. I do not have reference to the source right now, but will try to post later.
internal { sealed | static } class Module1 {
#if sealed
private Module1() { }
#endif
public static void Method1() { }
public static string Method2() { return "here"; }
}
Calling Module Methods
Module1.Method1();
string foo = Module1.Method2();

Categories