Link to home
Start Free TrialLog in
Avatar of m8online
m8onlineFlag for Netherlands

asked on

translating a windows app from VB.NEt to C++/C# , or how to use the same GUI in different platforms

We are developing a .NET DLL to control our hardware.
For this we want to provide a couple of demo applications in different programming languages.
We currently have a demo in VB.NET.

We would like to have exaclty the same application also in C++ / C#.

Is there a way to achieve this without starting all over again from scratch? can we somehow reuse the controls and their properties (size, location, settings) in another language.

Avatar of athapa
athapa

To copy your Forms,
open both projects in separate IDEs,
open the Form you'd like to copy,
Select All from the source Form and Paste into your new form in C# (or even C++/CLI).

For your code, you could use the tools like RemoteSoft's Salamander which will convert you existing assembly (compiled dll or exe) into C# or C++/CLI source code. If all you're trying to do is Vb.Net to C# then you can use a whole bunch of free online translation of Vb.Net to C#.  Converting to C++ is slightly tricky and that's where you'd want to use tools like Salamander.
Avatar of m8online

ASKER

I haven't got around to testing the GUI copying thing yet. This will probably work. Sometimes things are so simple that you just cannot see them. thanks for that.

About Salamander. I took a look at their website. It looks like a rather expensive tool.
Did you work with it yourself? What exactly does it do? will it also maintain the variable names used?

Would there also be an open source tool that does a basic translation?  It would be ok for me to have to clean up the generated code later.
I've use Salamander myself. If you have corresponding pdb files (generated while compiling in debug mode) for your exe or dll then all of your internal variable names will also get regenerated. Even without a .pdb files the regenerated codes are still readable. Besides Salamander there are few others commercial ones but I've not used them. There was one open source which I used long time back, Anakrino, but it hasn't been actively developed in a while.

As I mentioned before if all you need to do is Vb.net to C# then try these first before buying Salamander or other tools.
http://labs.developerfusion.co.uk/convert/vb-to-csharp.aspx
http://www.carlosag.net/Tools/CodeTranslator/
http://www.dotnetspider.com/convert/Vb-To-Csharp.aspx
http://www.kamalpatel.net/ConvertCSharp2VB.aspx

There are some windows apps too if you prefer not to use the online ones.
I tried copy-pasting from the VB.net project to a C++ project. This did not work.
The paste action just did not work.
Would one of the suggested tools also transfer the GUI?

I am thinking that I might have the wrong approach. A C# user would probable understand the VB.NET example application. Especially because it is nothing more than some glue between a GUI and the DLL which they would actually need.

The difference between VB.NET and C++ is more of a problem because the DLL is in fact a class library. For using it in C++ (no, user would not want to compiler with /clr) it would need to be converted to a classical DLL interface.
For this I am working on a wrapper DLL in C++ which would make an instance of the class and couple its member functions to the classical DLL interface.
This classical DLL could also be used from VB.net. So I could adapt the example app. to work with the two different DLL interfaces.

Current problem is that I cannot get the wrapper DLL to compile correctly.
In the code below the class CL_IO_ctrl is not recognized.

Any ideas?
// M8_IO_ctrl_classic.cpp : Defines the initialization routines for the DLL.
//
#using "C:\temp\IO_Ctrl\USB_IO_211_demo_app\V1_0_0\bin\M8_IO_ctrl.dll"
#include "stdafx.h"
#include "M8_IO_ctrl_classic.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
 
#define API_EXPORT __declspec(dllexport)
 
//
//	Note!
//
//		If this DLL is dynamically linked against the MFC
//		DLLs, any functions exported from this DLL which
//		call into MFC must have the AFX_MANAGE_STATE macro
//		added at the very beginning of the function.
//
//		For example:
//
//		extern "C" BOOL PASCAL EXPORT ExportedFunction()
//		{
//			AFX_MANAGE_STATE(AfxGetStaticModuleState());
//			// normal function body here
//		}
//
//		It is very important that this macro appear in each
//		function, prior to any calls into MFC.  This means that
//		it must appear as the first statement within the 
//		function, even before any object variable declarations
//		as their constructors may generate calls into the MFC
//		DLL.
//
//		Please see MFC Technical Notes 33 and 58 for additional
//		details.
//
 
// CM8_IO_ctrl_classicApp
 
BEGIN_MESSAGE_MAP(CM8_IO_ctrl_classicApp, CWinApp)
END_MESSAGE_MAP()
 
 	 class Cl_IO_ctrl IO_ctrl;
 
 
 
// CM8_IO_ctrl_classicApp construction
 
CM8_IO_ctrl_classicApp::CM8_IO_ctrl_classicApp()
{
// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}
 
 
// The one and only CM8_IO_ctrl_classicApp object
 
CM8_IO_ctrl_classicApp theApp;
 
 
// CM8_IO_ctrl_classicApp initialization
 
BOOL CM8_IO_ctrl_classicApp::InitInstance()
{
	CWinApp::InitInstance();
 
	return TRUE;
}

Open in new window

I tried copying vb.net form from the designer and paste in c++.
Here is what I did.
Open the vb.net solution.
Add a new c++ clr project
Open the form that needs to be copied in design mode.
Ctrl+A to copy all elements of the form
Add a new form in c++ file in cpp project
Go to design view of the new form
Ctrl+V to paste

But the method above or any of the tools mentioned previously will only work if you are trying to create c++/clr executables (or dll). If you are trying to use mfc or other framework for your ui then this method won't work.

If I understand you correctly then you're trying to create a wrapper for some 3rd party c++ component which (the wrapper) you'd like to use in dotnet applications. Is this correct? If so, do you need to use those component in c++ applications too?

No, it is the other way around.

I have created a class library DLL in VB.NET, and a VB.NET example app to show how to use this class library.

Now I want this class library also to be accessible to C++ apps.
I know that if C++ is compiled managed for .NET (/clr) it should be able to use a class library directly. However, as my customer wants his C++ environment to remain unmanaged, this is not an option for him.

Therefore I am trying to create a wrapper for the  class library. I Guessed the wrapper should be written in managed C++ and then expose al the member functions in the classical DLL way.

Then, because I am trying to avoid having more than one example app. I would use the same VB.NET example app, only now using the classical (GetProcaddress like) way to access the functions.
If you can, read this book
Expert C++/CLI:
.NET for Visual C++ Programmers

This book covers a lot of topic about manged code accessing unmanaged codes and vice versa.

I'm not sure if you'll be able to load vb.net classes using loadlibrary and getprocaddress. It probably would be easier for you to create a wrapper in c++ instead.

Your other alternative would be to use comvisible attribute in your vb.net class and access the class as com from c++.

Here is another approach but it seems convoluted.
Yes, Writing a wrapper DLL was indeed the way I wanted to go.

The problem which I am having with the wrapper DLL is that at the moment I cannot get it to recognize the VB.net managed class library.

I added the /CLR compiler switch
I added the VB:net managed DLL to "references"

Still the compiler says: undefined class: Cl_IO_ctrl
I forgot to paste the link in the last post.
Anyway, check this link.
http://www.codeproject.com/KB/dotnet/bridge.aspx

Depending upon the .net framework you're using c++/clr wrapper would be slightly different. The new framework (2.0+) uses slightly different syntax (such as difference in ~ and ! and a new ^, etc.) . One of the comment in the above article also takes a bit about the differences.

Can you post your wrapper code or section of it?

I did post the code which I had earlier in this topic. But I don't think it will tell you a whole lot because the only actual piece of code which I added myself is the declaration of an object which should be taken from the managed class library.

Meanwhile I have been doing some more experimenting and managed to at least get a managed C++ application to compile in such a way that the imported class got recognized. I was hoping that I could convert this to a DLL project later on.

The problem I am having now, is that I am not allowed to declare a managed object as global.

In the bridge example (http://www.codeproject.com/KB/dotnet/bridge.aspx)  the bridging functions create an instance of the managed class each time when they are called. Then when the bridge function returns the object is disposed.

I cannot use this principle for my class as it also has data members which need to be retained. Therefore I would need to create an instance (object) of the managed class when calling some init function and do not dispose it before the application ends.
The most logical way I could think of to do this would be to declare a global pointer to an object from the managed class library. Which is not allowed.
Is this possible in some other way?
By the way: @athapa.

I just ordered the book you mentioned. It looks very useful. Thanks!
You may have already resolved your issues. Anyway, I tested a simple program where a c# class is wrapped in c++ managed class. The c++ managed class is then accessed using loadlibrary in another pure c++ application. I was able to call the managed functions multiple times and retain the state (i.e. I didn't have to recreate managed object in every function calls).  In the c++ bridge, I added a static managed object. But you need to make sure you don't instantiate the managed object inside constructor or DLL_PROCESS_ATTACH/DLL_THREAD_ATTACH in DllMain.
No, in fact I am still working on it. I though I should read some chapters of the book before continuing. I just got it last week.

 Could I take a look at your source code?

I managed to get a static instance of the class using the GCroot. Now I am kind of stuck on how to connect the callback functions. The problem here is that I would want to create objects inside the wrapper handling the callbacks from each object in the managed world. Only you cannot use a method as a callbackfunction directly.
I took a look at functors, but they need such complicated code that I do not know if I will want to use those.
ASKER CERTIFIED SOLUTION
Avatar of athapa
athapa

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hello All,

Just to let you all know.
I am still working on this, but time pressure on some other project forces me to put it on hold regularly.
I will keep you informed on any new progress.