C++ binding plugin

This is where you talk about Plugins. How they are made and how they work, show examples.

C++ binding plugin

Postby coon » Sun Dec 10, 2017 12:38 pm

Hello there,

since I am not very familiar with C# I've written a C++ binding for UCCNC plugin interface so I can implement plugins for UCCNC using C++.
I've written this primarily for myself but it meight be useful for other people so I've deceided to make it public.

You can get it on github: https://github.com/coon42/uccnc-cpp-plugin

If you have any questions feel free to ask.

--------------------

Description

  • This UCCNC plugin allows implementing plugins in C++ instead of using any .NET language.
  • The .NET assembly which is loaded by UCCNC only acts as a gateway between C++ dll and UCCNC .NET plugin interface
  • The assembly loads the C++ dll after it got loaded by UCCNC

How to use

  • open uccnc-cpp-plugin.sln and compile it using Visual Studio 2017
  • switch to UCCNC installation directory (Usually C:\UCCNC\Plugins)
  • create cpp directory (if it does not exist already)
  • copy example.dll from Debug directory to C:\UCCNC\Plugins\cpp
  • copy plugin_gateway.dll to C:\UCCNC\Plugins directory
    rename plugin_gateway.dll to example_gateway.dll
    The assembly will load a cpp plugin depending of its name. If it is called plugin_gateway.dll it will load plugin.dll from cpp subdirectory. If it is called example_gateway.dll it will load example.dll etc.

Features

  • Use modern C++ without any feature limitations
  • Dynamic reload - Unload and reload the C++ plugin without restarting UCCNC
  • This allows updating the plugin without restarting UCCNC every time
  • Debug console for printf debugging
  • UCCNC has a copy protection which prevents you attaching the Visual Studio debugger to UCCNC. This makes it hard to debug your plugin. When compiling the C++ dll in debug configuration a console is attached to UCCNC so you can debug using printf.

Reasons for using C++

  • The author has very few knowledge about C# / .NET but strong knowledge in C++
  • The author was too lazy to learn C# just to write a plugin
  • UCCNC is written in .NET 2.0. Therefore any plugin (the assembly) has also to be written in .NET 2.0. Assemblies written in higher .NET versions cannot be used. Unfortunately .NET 2.0 is so old that many libraries (like MQTT) are not available for it.
coon
 
Posts: 15
Joined: Sat Dec 02, 2017 2:01 pm

Re: C++ binding plugin

Postby Haik » Thu Dec 14, 2017 4:42 am

Very nice. There's a lot to like in there. :) Thank you!

I totally agree with your take on the .net 2.0 constraint. I can't even use Linq.

If I may ask, are you able to fully debug (into) your projects? I've had to jump through some fiery hoops for the limited debugging I have now. Test also seems laborious. Maybe it's just me.

An tiny addition I've found handy is...

SETLOCAL EnableDelayedExpansion
IF $(ConfigurationName) == Release (
copy /y "$(TargetDir)$(TargetFileName)" "C:\UCCNC\Plugins\$(TargetFileName)"
)

Kind Regards,
Haik
Haik
 
Posts: 14
Joined: Fri Sep 08, 2017 6:01 pm

Re: C++ binding plugin

Postby coon » Thu Dec 14, 2017 7:40 pm

It is not possible to debug UCCNC using Visual Studio. Visual Studio does close itself if you try to attach the debugger to UCCNC.
The only way I debug is using printf. This gives me kind of a trace which helps alot in most cases.
This is how it's looks like:

https://i.imgur.com/OSTMHyf.png

Copying the plugin to UCCNC plugin directory every time after building a new version is nasty indeed. I will add an after build event to automate this process. The problem with your approach is, that not everyone meight have installed UCCNC to C:\UCCNC. However, you can geht the installation path from the registry: HKEY_CURRENT_USER\Software\CNCdrive\UCCNC -> InstallPath.

I am also thinking about implementing some kind of UCCNC remote debugger + plugin for it. For debugging you load your plugin into the remote debugger process. The remote debugger plugin, which is loaded by uccnc, will connect to the remote debugger process and passes all calls via sockets or windows pipe. Since the plugin is running in another process, it can be debugged without any problems. Shouldn't be big deal to implement that.
coon
 
Posts: 15
Joined: Sat Dec 02, 2017 2:01 pm

Re: C++ binding plugin

Postby cncdrive » Thu Dec 14, 2017 10:22 pm

Hi,

First of all, thank you for developing this plugin loader. I'm sure many folks will find this useful in the future.
Second, you gave me a good idea with mentioning that you can't debug the UCCNC which is true, because if it was debuggable then the software would become vulnerable for crackers.
And you are right the UCCNC.exe can't be debugged, because it has a protection.
So, the idea you gave me is to redirect the Console output to a plugin window. I think I'll make a plugin which will do this, so it will be easier to debug macros and plugins, because then the Console.Write and Console.WriteLine datas will be seen on the plugin window.

I think it can be done easier than using sockets or pipes with redirecting the standard output of the process (console), like: Console.SetOut(TextWriter); and then ofcourse get the data from the Textwritter object, attach events to catch the WriteLine and Write occurances and post the data in e.g. a listbox.
cncdrive
Site Admin
 
Posts: 2003
Joined: Tue Aug 12, 2014 11:17 pm

Re: C++ binding plugin

Postby Dan911 » Thu Dec 14, 2017 11:03 pm

coon wrote:Copying the plugin to UCCNC plugin directory every time after building a new version is nasty indeed.


Changing the output path in VS to the UCCNC/plugin folder will eliminate this, UCCNC needs to be closed though.

Dan
Dan911
 
Posts: 369
Joined: Mon Oct 31, 2016 1:22 am
Location: USA

Re: C++ binding plugin

Postby coon » Fri Dec 15, 2017 10:23 am

cncdrive wrote:Hi,

cncdrive wrote:I think it can be done easier than using sockets or pipes with redirecting the standard output of the process (console), like: Console.SetOut(TextWriter); and then ofcourse get the data from the Textwritter object, attach events to catch the WriteLine and Write occurances and post the data in e.g. a listbox.


This is what I am already doing with my plugins. I am attaching a console to UCCNC process via Kernel32.AttachConsole(), set stdout to that console and use printf. What I am planning to do is something different.
I want to marshall all function calls between UCCNC and and the plugins via sockets / pipes. Instead of loading the plugin into UCCNC I want to load the plugin into another process, so I can attach Visual Studio debugger and can do step by step debugging.

For example:
When I click a button in UCCNC, the Buttonpress_event() function in the UCCNC proxy plugin is called. I then could marshal the function name + parameters and send it via sockets to my other process where the actual plugin is loaded. I then block execution in proxy plugin and wait for socket data. As soon as I have received the marshalled data in the other process I will unmarshal the function call and Buttonpress_event() inside the real plugin is executed. After execution the return value (if there is any) will also be send back via socket to the proxy plugin and the call stops blocking.

The Idea is, that the plugin does not run in UCCNC but in another process, so debugging gets is possible.
coon
 
Posts: 15
Joined: Sat Dec 02, 2017 2:01 pm

Re: C++ binding plugin

Postby coon » Fri Dec 15, 2017 10:25 am

Dan911 wrote:
coon wrote:Copying the plugin to UCCNC plugin directory every time after building a new version is nasty indeed.


Changing the output path in VS to the UCCNC/plugin folder will eliminate this, UCCNC needs to be closed though.

Dan


With my plugin loader you don't have to. You can unload, update and reload the plugin while UCCNC is running. It should also be possible reloading the plugin while milling but I didn't test it yet. :p
coon
 
Posts: 15
Joined: Sat Dec 02, 2017 2:01 pm

Re: C++ binding plugin

Postby cncdrive » Fri Dec 15, 2017 3:37 pm

This is what I am already doing with my plugins. I am attaching a console to UCCNC process via Kernel32.AttachConsole(), set stdout to that console and use printf. What I am planning to do is something different.


What possible issue I see with this is that you can't remove the console without killing the UCCNC process.
As far as I remember attaching a console that way will basicly make the console to be part of the UCCNC process and when you free the console it will kill all the processes attached to it.
I'm not 100% sure now, but I remember that it works that way in Windows since probably XP. But I did not have time yet to test it, so if I'm wrong then please let me know.

What I want to do is to set the stdout to a TextWriter and then attaching events to catch changes in it, so when e.g. WriteLine happens the data can be output to e.g. a ListBox.
This way there is no need to attach a console to the UCCNC process and so closing the console will not kill the UCCNC.

I think using pipes or sockets is a great idea for what you want to do, I just said that to get a console can be done easier than that, but what you want to do is much more than just adding a console and for that in my opinion using pipes and sockets is a good way to go. You could even run "plugin" processes then on another computers interacting with the UCCNC. :)
cncdrive
Site Admin
 
Posts: 2003
Joined: Tue Aug 12, 2014 11:17 pm

Re: C++ binding plugin

Postby coon » Sat Dec 16, 2017 1:05 am

The console can be detached, without closing UCCNC. I am doing that already, when all cpp plugins got unloaded. However when you close the console by clicking X, UCCNC will close too but I prevent this by disabling the close button of the console.

Running the plugin on another computer sould work indeed. :D But this is just a funny side effect, which I don't plan to support, since I don't see any benefit doing so.
coon
 
Posts: 15
Joined: Sat Dec 02, 2017 2:01 pm

Re: C++ binding plugin

Postby cncdrive » Sat Dec 16, 2017 2:31 pm

Yes, that is exactly what I thought about that if the user closes the console then is kills the UCCNC.
And that side effect that you could run the plugin on a separate computer may be useful for some people, e.g. when computers are connected up in a network and the user wants to do stuff remotely,
and if for example the user wants to show data on another computer, on another monitor. It is more often that people want to do these kind of things than you might think. :)
cncdrive
Site Admin
 
Posts: 2003
Joined: Tue Aug 12, 2014 11:17 pm

Next

Return to Plugins

Who is online

Users browsing this forum: No registered users and 2 guests