I currently have the following setup:
Application (executable)
C++ DLL (contains logic used by the executable and loads the C# DLL, temporarily has a console window for debugging)
C# DLL (contains GUI)
The C# DLL uses a nuget package called UnmanagedExports in order to provide functions to C++. The method ShowGui() is provided by C#.
The C# DLL is loaded using LoadLibrary() and the ShowGui() method works correctly. However, I seem to have trouble understanding how I would go by implementing a function that allows C++ to send a message to C#.
Currently I came up with the following:
[DllExport("AddDebug")]
public static void AddDebug([MarshalAs(UnmanagedType.LPStr)]StringBuilder s)
{
guiMain.AddToTextbox(s.ToString()); // the GUI uses BeginInvoke to prevent cross-thread exceptions.
}
In C++ I have simply changed printf() to AddDebug() and this seems to work only half the time: at a certain point the C++ DLL gets blocked when trying to call AddDebug() and gets unresponsive.
I have used the following to debug in C++ (obviously calling sendDebug instead of AddDebug):
sendDebug(string s)
{
cout << s;
AddDebug(s);
cout << s;
}
In the scenario of C++ blocking, the above code only displays the string s once and is never displayed by C#. Meaning AddDebug() is never completed.
I have tried looking for solutions but it doesn't seem to work the way I want it to. Changing to a complete C# solution is not an option as the C++ code is insanely large and would take too much time to "convert".
I hope my question is clear and that somebody maybe has a suggestion to keep me from pulling my hair out. Thanks in advance.
Eventually I ended up implementing a Named Pipe. C# being the server and C++ being the client. Seems to work without any issues.
Related
i wrote my program in visual studio 10 with c++ but now i want to make dll of it to use it with interface of visual c# , i am using command line argument in my program for input
I saw tutorial from here , but my code is not as small as there , i have 1000 of lines , so i can not wrote like this
static __declspec(dllexport) double Add(double a, double b);
for every line and am also using opencv library in it so whats the other way to create the dll of c++ program , or how can i simply use it with c# interface .
There are several ways in which two programs can interact.
Even with __declspec (dllexport), it's not to be added to each and every line of your program. Rather, you need to add it to the "exported functions". So, the first thing you need to do is to create a list of functions that you want to export from your C++ program. You might get better responses here if you provide a bit of more insight into what your interface will look like.
Beyond DLL's, there are other ways through which programs can interact. Even file I/O is a possibility, when there is no other way feasible, where one program writes to a file as an input and the other program reads it.
I have designed the code in MATLAB and it's working fine. I was working in GUI in MATLAB but it's a headache for me. I think i can create GUI simply and effectively. Can we create GUI in C# that will also run the whole code of MATLAB that i have designed??
Yes, this is possible. For details, take a look at:
Calling a MATLAB function from C#
Integrating MATLAB with C#
MATLAB Compiler
If you need a quick and dirty way to wrap MATLAB code with a C# GUI (e.g. WinForms), one option is to create an exe from your MATLAB code (.m) - from .NET, you can then easily start this exe as a new process. Note that this approach may not be the best in some situations, beacuse the delay introduced with an exe call can be quite substantial (as the other answer explains).
An example: first, write MATLAB code as a function:
function y=SamplePlot(p, d, w, t)
numericValueP=str2num(p);
numericValueD=str2num(d);
numericValueW=str2num(w);
time=str2num(t);
%... do stuff ...
plot(...);
Input parameters will be passed to this code as string parameters via command line, hence they are converted via str2num. E.g. a MATLAB call
SamplePlot('1', '2', '3', '4')
will be represented as
SamplePlot.exe 1 2 3 4
Now, create a standalone console app from .m file: in MATLAB console, write:
deploytool
Name: SamplePlot.prj (for example). Target: Console application.
Add .m file.
Package: add MCR (this is MATLAB Compiler Runtime - this is what an end-user will need if he doesn't have MATLAB installed; for local testing, you don't need to add this).
Then use:
mbuild -setup
Finally, click 'build' icon. After some time, an exe is generated. Now, you can start this exe as a process from a C# application, e.g. on button click:
private void button1_Click(object sender, EventArgs e)
{
string p=TextBox1.Text;
string d=TextBox2.Text;
string w=TextBox3.Text;
string t=TextBox4.Text;
string params = String.Format("{0} {1} {2} {3}",p,d,w,t);
System.Diagnostics.Process.Start("SamplePlot.exe", params);
}
I left out some minor details, but this is one possible option.
(If I recall correctly, an assembly can be generated this way as well; you can then call the assembly instead of an exe file).
I'm pretty unfamiliar with C# but eventually happened to use .NET classes from MATLAB.
So, you could also do it the other way round, than the previous answers suggest:
Since MATLAB is able to create/open .NET gui-elements like dialog, I guess you should also be able to open your .NET-GUI from MATLAB an then plug in your MATLAB-Code via Callbacks.
See e.g.:
http://www.mathworks.de/de/help/matlab/matlab_external/getting-started-with-net.html
Depending on how frequently you want to execute matlab-code from your gui and how long the matlab-processing time usually is, this also avoids the pretty large overhead that's e.g. introduced by using a .exe generated with the MATLAB compiler.
Say, you'd like to do quick matrix-calculation operations taking less than a second with every other button-click, than starting a standalone.exe everytime would make your gui pretty useless.
This link is so useful and simple:
Call MATLAB Function from C# Client
At the request of my boss I created a small set of scripts that are used to periodically monitor the status of certain devices and processes. This info is subsequently processed using a relatively elaborate VBA module that gathers all info, applies formulas, sets up ranges and generates graphs, etc.
There are two problems however:
I'm an amateur programmer, so my VBA routine is quite inefficient. That's not a huge problem for me (I just get up and get a coffee while it's running), but for other users this can be a hassle, as then don't know why it's taking so long. I want a graphical representation of progress.
The configuration of the application is done through a text file. I want to provide a decent GUI for setting up the configuration.
In order to achieve this, I'm looking for a way to let my C# WinForms application communicate with my VBA application. I know how to run a VBA routine from my C# app, but I don't know how I can let them comminicate in real-time.
Here are the two things I specifically want to achieve:
I already have a log file that's saved at the end of the VBA routine.
Instead of that however I want to send the log/debugging-messages to
my C# application in real-time (not just at the end of the
application) so the messages can be displayed in my GUI app as they
are generated by the VBA app.
I also want the VBA app to send info
about real-time progress to my GUI app so I can create a graphical
progress-bar in my GUI app.
I've already thought about communicating through the Standard Output. I know how to read from the Standard Output using C#/.Net, but I'm not sure how I would write to the StdOut stream using VBA.
I'm sure many would point out that what I'm trying to achieve is stupid and old-fashioned (or totally unnecessary), but as an amateur programmer it seemed like a really challenging and fun project for me that could teach me a thing or two.
Creating a C# COM-visible class is pretty easy, and (as you said in your comments) it is fun. Here's a small sample.
In a new C# Library project, add:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CSharpCom
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
//The 3 GUIDs in this file need to be unique for your COM object.
//Generate new ones using Tools->Create GUID in VS2010
[Guid("18C66A75-5CA4-4555-991D-7115DB857F7A")]
public interface ICSharpCom
{
string Format(string FormatString, [Optional]object arg0, [Optional]object arg1, [Optional]object arg2, [Optional]object arg3);
void ShowMessageBox(string SomeText);
}
//TODO: Change me!
[Guid("5D338F6F-A028-41CA-9054-18752D14B1BB")] //Change this
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
interface ICSharpComEvents
{
//Add event definitions here. Add [DispId(1..n)] attributes
//before each event declaration.
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(ICSharpComEvents))]
//TODO: Change me!
[Guid("C17C5EAD-AA14-464E-AD32-E9521AC17134")]
public sealed class CSharpCom : ICSharpCom
{
public string Format(string FormatString, [Optional]object arg0, [Optional]object arg1, [Optional]object arg2, [Optional]object arg3)
{
return string.Format(FormatString, arg0, arg1, arg2, arg3);
}
public void ShowMessageBox(string SomeText)
{
MessageBox.Show(SomeText);
}
}
}
You will want to go into your project properties, to the "Signing" tab, check the box to sign your assembly, and create a new "strong name key file". This will help to prevent versioning issues with your registered DLL.
Compile it, and register the DLL using regasm in a Visual Studio command prompt. You will use either 32 or 64-bit regasm depending on what version of Office you are using... you will find RegAsm in C:\windows\Microsoft.NET\Framework or C:\windows\Microsoft.NET\Framework64 (32 and 64-bit, respectively):
C:\windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase /tlb CSharpCom.dll
This will register your DLL with Windows, so now in the VBA editor, you should be able to go to Tools->References and find your COM's namespace "CSharpCom". Check that box, and now you should be able to create your COM objects in VBA:
Sub TestCom()
Dim c As CSharpCom.CSharpCom
Set c = New CSharpCom.CSharpCom
c.ShowMessageBox c.Format("{0} {1}!", "Hello", "World")
End Sub
You can add forms to your COM object, and open them when the VBA calls a particular method; you should be able to use this to create a form with a progress bar. One thing to consider, though, is that VBA is single-threaded. This means that everything else gets frozen while your code is running, so things might get a little tricky.
Off the top of my head, you could create 3 methods in your COM-visible class: one to open the form, one to update progress (call VBA's DoEvents() method right after your VBA calls the update() method on your COM object, to allow Office to process screen updates), and one to close it. You should call Dispose() on the form; which could be done in the "close" method, but I think it could potentially cause memory leaks/problems if your VBA crashes, and your close method is never called -- just something else to consider.
You can use a .NET DLL with your VB6 project and create an instance of any object you have defined in your assembly. This is done by registering the .NET assembly (.dll) for COM interop (use in VB6) by creating a type library file (.tlb). The .tlb file contain extra information so that your VB6 project can use your .dll. Note, your VB6 project will not reference the .dll but the corresponding .tlb file. You can use the Regasm.exe utility to generate and register a type library and register the location of the managed assembly. Then its just a matter of creating an instance of your .NET object, whether it be a WinForm or some other cool class. =).
Dim MyDotNetObject As MyDotNetClass
Set MyDotNetObject = New MyDotNetClass
MyDotNetObject.SomeMethod(value1, value2)
''end of execution
Set MyDotNetObject = Nothing
See: http://support.microsoft.com/default.aspx?scid=kb;en-us;817248
I believe the code in this link does roughly what you want:
C# code creates a COM object (in the example it is IE, but from your description, you have already managed to create an instance of your VBA routine)
It attaches a .Net event handler (using +=) to an event raised by the COM object (when the title changes)
It defines sample event handling code
http://msdn.microsoft.com/en-us/library/66ahbe6y.aspx
I don't profess to understand this code, my objective is to show convoluted this solution would be! You should really build this in just one solution. A total VBA will solution will be quicker to develop (you only need to learn VBA forms which is easy), but old technology. A total C# solution will be slower to develop but then you will get to learn C#.
Performance actually is an issue. If it performs inefficiently now, what happens when you have 5x as many records to process? You should solve the performance issue before you get that many records.
The other answers to this question involve the VBA macro calling an external method. But there is an easier way. Your GUI app can attach to the workbook SheetSelectionChange event or sheet Change event, which will be triggered when any value changes.
Because you probably don't want to slow down everything, I would recommend adding an additional sheet, add named ranges to describe what each value means, then hook the sheet change event to intercept when these values are changed and update your GUI.
I have the problem loading the DLL file and calling the functions in Python.
I have tried a lot of tutorials, but still can't figure out how it works.
This is my class to export as DLL file. I use simple C# code.
namespace DemoClassLib
{
public class cLib
{
public int increment(int x)
{
return x + 1;
}
}
}
After building the C# code, I get the DLL file called "DemoClassLib.dll".
I use ctypes to load the DLL file. Everything is okay until now.
from ctypes import *
myDll = WinDLL('D:\\Resources\\DemoClassLib\\bin\\Debug\\DemoClassLib.dll')
Starting from that point, I can't continue.
All the commands I have tried are failed.
n = c_int(1)
myDll.increment(n)
It keeps on showing me the errors.
How can I call the method "increment()" in Python?
And how can I pass the input and retrieve the output from that?
I am very new to Python.
Can someone help me please?
I would be very appreciated if you can provide me the source code tutorial.
You can't do this with ctypes because there is no symbol in the binary called simply "increment", as your increment method is a member of a class. Even if this were C++ the name would be mangled. But with C# you don't even get a mangled name in the symbol table because the code is interpreted by the .NET framework.
If you must for some reason interface with a C# library you may want to consider trying IronPython (http://ironpython.net/) which is Python running on the .NET framework with full access to the CLR. The comment above suggesting exposing a COM interface could also work.
I've got a problem which I hope you can help me with.
I created ASP.NET 4.0 web application. I've also got .cpp file generated in some other app. This .cpp file contains functions, which always returns the same number of variables and which always takes the same number of parameters.
What I need to do is being able to use this functions in my web application.
But what is real problem is that I need to be able to replace this functions while running app. What I mean is administrator should be able to login, upload new cpp file, which will replace old functions with new ones. New ones will have the same names, parameters and result number, but will make calculations in a different way.
Is there any way this can be achieved?
Thanks for any help!
MattheW
Precompile the cpp code into dlls and let admin upload dll. Reference dll's from c# app using [DllImport("")] directive.
C++ will need to be compiled in some way or another. You can use a compiled dll written in C++ in your ASP.NET application but the code will still need to be compiled for ASP to be able to use it.
The compiled DLL can then be loaded and unloaded to accommodate changes to the function. You could perhaps even make the ASP.NET server compile the file somehow, but the code still needs to be compileable to a DLL to make it executable.
You need to expose the C++ code via another dll.
The first choice is pinvoke. See:
How to set up a C++ function so that it can be used by p/invoke?
It's also covered here:
http://msdn.microsoft.com/en-us/library/aa446538.aspx
Technically you could also expose via COM or write in managed C++ but those are both overkill if you're just trying to expose a few C++ functions.