I have to communicate with a controller that uses an unmanaged DLL in C#. The documentation isn't very helpful for the DLL and I have no experience with talking to DLL's. The company does provide a sample VB project with a class that wraps the DLL from VB. The class is called ctccom32v2.
I thought that since the dirty work of calling the unmanaged DLL is already done including structs and other variables, I could use that class to create a VB class library. I figure it will save me a lot of time and effort. So I added that class source file to a VB class library project and it spat out a dll when built. I then added that dll to my C# project references and I am able to see the functions in the reference browser. The library I created is named CTC_Lib.
(if your wondering why I just don't write my program in VB and use their class, I prefer and I am more comfortable working in C#)
The problem I am running into is this:
If I create an instance of the library using
CTC_Lib.Ctccom32v2 ctc = new CTC_Lib.Ctccom32v2();
and then attempt to type ctc.somefunction, intellisense shows a few default methods like Equals, GetHashCode, etc. I do not see any of the Ctccom32v2 functions which expose the unmanaged DLL.
if I type the library and class name manually like so:
CTC_Lib.Ctccom32v2.
The intellisense list pops up with all of the functions in Ctccom32v2.
If I add another class to the VB class library (Lets call it "somelib") and stick a simple function into it:
Public Function add() as Void
Return 1+2;
End Function
I then use the same method for creating an instance:
CTC_Lib.somelib ctc = new CTC_Lib.somelib();
the function "add" now pops up in the intellisense window by simply typing ctc.
Could it because the way the functions are declared in the VB class? Here is one of MANY functions in the VB class, they are all declared the same using "Declare Auto Function":
Declare Auto Function CtOpenConnection Lib "Ctccom32v2.dll" _
(ByVal ConnectID As Integer, ByVal CommPort As Integer, ByVal Address As Integer) As Integer
I don't know what Auto function means but that does not expose the function when you attempt to create an instance of the class it resides in.
If this is or is not the proper way to call those functions within the VB class library please let me know, I am a novice. Also, forgive me if some of my terminology is incorrect; I am not good with programming jargon (yet).
The intellisense differs in your two scenarios because the unmanaged DLL lacks the required metadata to properly display the information about the functions. Your VB function does possess that metadata.
You already know the workaround; type the library and class name manually. Alternatively, you can wrap the unmanaged functions in managed VB methods, which will provide the needed metadata for intellisensing.
See the MSDN documentation on the Declare statement. This looks similar to declaring an extern method in C#. I think what you're missing is the access modifier. It should be like Public Declare ... to allow it to be used outside of where it's declared.
If that wasn't the issue, you might want to declare it as a Public Shared Function in a public class, using DllImport. An example of that is shown at the bottom of the Declare statement doc.
It can also be useful, maybe for this, and for C#/VB conversions in general, to decompile your assembly in ILSpy and see what is generated due to these lines.
Related
I need to create the classes in C# and call that classes from javascript through C++CLI and Firebreath Framework .. create the complex hierarchy class structure and expose it from javacsript
The flow should be :
Javascript <-- C++(FireBreath)<-- C#
C#-->C++(Firebreath)-->Javascript
I have to create the generalized solution for this problem.
Then how should i implement this? If you have any solution,sort of information ,ways to solve this problem then please let me know..
Suppose my Class Library in C# which includes the classes like :
public class TestImage
{
}
public class DrawImage
{
public void ShowImage(TestImage testImage)
{
}
}
Here I need to call ShowImage(TestImage testImage) method from JavaScript page of Firebreath Framewaork.
I already created the wrapper but I dont have an idea to expose the class object as argument to the method like the above ShowImage () in tjhe JavaScript page of the Fireabreath Framework.
If you have any idea related to this please let me know.
When you say "generalized solution"... do you mean a tool or process that automates this?
I believe this is possible. Here's how I would do it:
I'm assuming you have gotten started with FireBreath and have some understanding of it. I'm glossing over countless problems you'll run into integrating all this within a FireBreath solution; that would take days! So this is just architectural advice. I'm sorry to omit so many details.
I would write a tool that dynamically loads your .NET assembly or assemblies, and uses reflection to traverse the 'complex hierarchy class structure'. This tool would generate two things: A C++/CLI wrapper for your .NET library, and a set of native C++ FireBreath classes that bind from Javascript to that C++/CLI wrapper.
The C++/CLI wrapper (see enter link description here) makes your .NET library callable from the native C++ of FireBreath.
Actually, here is a tool on CodePlex that claims to generate such a wrapper.
The Javascript adapter is a set of .cpp modules (probably one for each of your library/C++/CLI classes). Each of these is a C++ class derived from FB::JSAPIAuto, which allows these classes to be instantiated as Javascript objects. Within the constructor for each of these classes, the automated tool inserts code to create the object's Javascript API. Code that looks like this:
registerMethod("Start", make_method(this, &thisClass::Start));
registerMethod("Abort", make_method(this, &thisClass::Abort));
registerProperty("Size", make_property(this, &thisClass::get_Size,&thisClass::set_Size));
The automated tool must synthesize these methods of the class, like thisClass::Start and thisClass::set_Size. Their parameters and return types are the Javascript-compatible types supported by FireBreath - like int and double and bool, but also std::string, FB::VariantMap and FB::VariantList. In the body of each such method, the tool generates code to call the corresponding C++/CLI wrapper API, doing any necessary conversion between parameters and returns.
I suppose that each FB::JSAPIAuto-derived class inherits from, has as a member, or holds a pointer to, the C++/CLI class/object it represents.
As a FireBreath project, your .NET library is ultimately represented by a GUID - this is how Javascript finds its way into your library, by creating a root object from that GUID. It then calls methods or reads properties of that object to get other objects, and so on to access your entire library API.
I suppose there will be some issues mapping between Javascript and C#. You will have to study the Javascript parameter and return types supported by FireBreath, and limit your C# API accordingly. Probably key is figuring out how Javascript objects and arrays are represented as they cross the C++/CLI layer.
I've just achieved something like this using COM. I exposed the C# library as a COM object, then wrote a couple of wrapper functions which called this library in FireBreath. (I was lucky thought I had a very simple API).
The issue is fairly simple, I have some constants in a C++ namespace that I would like to wrap using SWIG 2.0.8. It looks something like this:
namespace Example {
static const float PI = 3.14159f
...
/* Lots of classes are here */
}
Unfortunately SWIG handles this rather awkwardly. In the C# case, it adds the constants to a class with the same name as the namespace so it must be accessed by using Example.Example.PI even when I am explicitly using Example (due to masking by the module name).
In Java, its even worse as it does not treat it as a constant at all and I am forced to call it using Example.getPI() as a method call instead of a constant class variable.
If I move the constants to the global namespace, this seems to work but then the variables must be accessed using ExampleConstants.PI.
Ideally, I would like both languages to be able to access the constants via Example.PI to be consistent with C++. But a compromise that I would be happy with is if I could have a Constants class inside my namespace so that I can use Constants.PI in either language. But of course, C++ does not allow non-integral types to be defined inside a class and this is still not solving the issue in Java.
Is there any elegant way to handle these namespace constants with SWIG?
And if not, is there a way I can manually add a Java or C# class to define them?
I solved similar problem for C++ - C#. I am not sure if this is exactly what you are looking for, but I hope you will find some info useful for you.
I have not touched Java code in my project.
Swig solution.
I created class with public static parameterless functions in C++.
Then I exported them to C# using SWIG.
I specified namespace for C# in command line with -namespace <name> key. More details available at page SWIG and C#
As a result you can impelement solution to access your constant with Constants::PI() and Constants.PI()
Direct solution
If you would like not to use SWIG or other library, you should use PInvoke. There are a lot details and special cases when working with it. Most comprehensive article on subject I have found is Mono Interop with Native Libraries
You should consider JNI for Java.
Note, that C++ functions are exported without namespaces as pure C functions and you should create C# class and create functions with DllImport attribute to wrap functions back to namespaces.
In general if your C++ interface is more or less fixed and/or small I would adhere direct solution, because SWIG layer has many-many specific cases which should be learned along with PInvoke/JNI. But if you C++ interface frequently changed and requires a lot of effort to keep C++, C# and Java consistent, you defenitely need to consider SWIG.
You may find non-trivial example using PInvoke at https://stackoverflow.com/a/11909571/13441
Concerning C++ constants. You can specify C++ constant inside class, refer to C++ static constant string (class member) for details.
I use SWIG 1.3.40.
Hope this is helpful.
This is my first major application using multiple classes. It is written in vb and I know about creating objects of the class and using that instance to call functions of the class. But how do I create an object with constructors to allow another program written in C# to access my classes and functions and accept things from the program.
Hope this makes sense.
Simply create a .NET class library and include that library as a reference inside the C# program. In .NET all libraries are .DLL files.
Once you do that the library will be available to C# with C# syntax.
You need to compile your VB classes into a class library (DLL) not an application.
From you C# application you need to add a reference to your newly compiled DLL. This DLL contains the classes and methods that you can instantiate and call from C#.
Once you've added a reference to the VB DLL from your C# assembly, you can access the VB classes (mostly) as though they were all in the same assembly. (I say mostly because access modifiers can change this, especially the 'internal' access modifier).
Dim myClassInstance As New MyClass()
edit: Ah, you want to define a class with constructors?
If that is the case, try this:
Public Class MyClass
Public Sub New(myNumber As Integer) 'Defines a constructor with an Integer as argument
End Sub
End Class
I'm attempting to consume a dll written in C++ from a C# application. I have 3rd party source code for the C++ dll (the Cyclone physics engine) and do not want to manually port it over to C#.
In the C++ project
I changed it to output a dll. I changed it to use the /clr flag. I changed it to use Multi-threaded Debug DLL (/MDd) because that was the only one compatible with /clr and also compiled.
In the C# project
I added a reference to the dll. I'm using the cyclone namespace.
At first there was absolutely nothing under the namespace. I think this is because in the C++ code, all classes were declared with no access modifiers and the default is private. So for the class "Particle" I changed the definition to:
public class Particle
{
//...
}
Now I can successfully declare a variable of type Particle from the C# code. However, intellesense and the object browser report Particle to be a struct (?) and it doesn't contain any methods at all. The c++ code declares a bunch of methods after "public:" access modifiers so I don't know what the problem is.
For example,
public:
void integrate(real duration);
What am I doing wrong?
The Particle class is not a managed class, hence it is treated as a struct. You need to use the ref keyword to make it managed and garbage collected. You also need to do the same to every other class that references it which might be a problem. The best solution I think, is to create a managed wrapper class that uses the Particle class internally. This wrapper class can then be referenced by .net.
See here:
I have not actually run into your exact problem before, but I have used C++ dlls in c# before. Typically when calling a dll like that you would use the dllImport keyword. Basically you can define a class that imports all the types and methods from the c++ dll. You can then call those wrapper classes.
I am far from an expert on it, but I have used it to get access to win32 methods and some other libraries that I needed to use.
This link on codeplex has a few links tools that might help. But the most important is probably the Interop Assistant. It can generate the C# wrappers for your c++ dll.
This isn't exactly what you are asking, but I thought it might help to look at a different direction.
Try declaring the c++ class with the ref keyword:
public ref class Particle
Do you have a reference to COM Interop?
I have added a C# DLL into a C++ project as mentioned at MS support, however I was not able to access its variables and methods inside the class. It also says that it's a struct and not a class, I don't know if it is important but I thought I should mention it is as well. Whenever I write . or -> or :: after the object, nothing appear. But it appear at the name of the class only although they are not static.
Starting with Visual Studio 2005, you can use C++/CLI, Microsoft's ECMA-approved C++ dialect that allows using managed and unmanaged code together. In VS2005, there are the "Managed Extensions for C++", with which you can achieve roughly the same, but you have to use horribly-looking syntaxes for writing managed code in C++ (with lots of double underscores).
With C++/CLI, you can mix managed and unmanaged code in your project, and use C# types directly. IMHO, that's a lot easier than using COM.
To increase compatibility I don't export a class from my DLLs (C# or C++). Instead I expose the class's functions, but the first parameter of each function is a pointer to the class itself. Of you could you also need to expose a: void* CreateMyClassInstance(), and a: DestroyMyClassInstance(void* pInstance).
Read the article posted on below link
http://www.codeproject.com/KB/cs/InterOp.aspx
I think it would help you out.