c++ structure pointer cast as array interop c# - c#

Preface:
I have a legacy c++ application which has a COM component. One of the methods goes
HRESULT foo(int* returnInteger)
Although the initial implementation was designed to return single int, the program evolved such that the classes which implement this, now return a list of integers instead of one.
returnInteger = memalloc((number of integers)*size of integer)
and the caller also reads the return pointer by
number of integers returned = sizeof(returnInteger)/size of integer
I know this design is not pure COM, not ideal and was not designed keeping interop in mind. But, I have to make-do with what I have.
Current problem:
Designing a c# application which uses the component. I know I will have to slowly phase it out, but for now, I have to continue with the same
c# shows the method as
foo(ref int returnInteger)
The c# application will read only one int (even though the c++ client is sending over an array of integers). How can I get the c# application to behave the same as the c++ client and read the array of integers?
Any help on this is much appreciated

Found a workaround for this: Using managed C++ as a middle layer.
Although not the most ideal solution, since I could not modify the legacy code, this is the route which favored me the most.
Thanks a lot for all the help

Related

How to pass an array of structs from c++ to c#?

I have been researching this for a while but can not find a solution.
I am writing a program that is using a c++/CLI wrapper. My goal right now is to return a list of all running processes and their PID (among other information) to c#. I have a running C++ function that returns a vector of type PROCESSENTRY32, but don't have the slightest clue how to get that information to c#.
I know there is a function in c# to get all running processes, but I'm trying to do it in c++.
Any tips or pointers in the right direction would be great.
First, set up an api for your c# application to access data from. Declare your API functions with __declspec(dllexport) just before your C++ functions return type. Using a #define for this can be handy.
In C# land, make sure you have using System.Runtime.InteropServices; Then, make a static method handle for your api using [DllImport("dll_name.dll", CharSet = CharSet.Unicode)] method attribute for your method then static extern returnType CallCPPFunction(); You'll have to write a custom data parser using this method as the returned data is simply a bunch of bytes (Meaning C# will attempt to cast the received data from C++ as the return type you specify in C#). You could make a struct in C# constructed with a byte array, and set that as the constructor parameter, however, you can make your job a lot easier by sending one or more int* as parameters to the C# function that hold useful data like sizeof(object) or significant markers in the objects data to make parsing it easier. Keep in mind the memory here is simultaneously managed by C# and C++, so if you pass an int* holding the sizeof(object) you'll still need to delete that pointer in C++, but make sure you don't do stuff like that when C# or C++ is still using the data. You could do some unsafe code in C# where C++ passes a bool* that starts as false, then C# marks it as true when it's done reading the data.
I'm not an expert in this Marshalling business, but I have successfully used this exact method of transferring data in this manner in the past. It's entirely possible there's some way to use the C++ types in C# so that this data parsing isn't necessary, or C# somehow using the .h files to do stuff, but if there is, I don't know it. Here's the tutorial that I watched to figure out the concept myself, but it's a bit long and I couldn't find another one that was the same thing I was looking for:
https://www.youtube.com/watch?v=w3jGgTHJoCY
If I'm not mistaken, the data parsing won't even be necessary if you re-create the C++ struct in C# such that the first data member defined is the same associated data member in the C# struct, second C++ member to the second in C# etc. Keep in mind the size of the data types needs to match, or the data will be offset once it hits a data member whose size in C++ and C# don't match. If your struct contains sub-types you'd need to re-create those in C# too; all the way down to the primitive type level.

Passing Structure to C#

I am writing code to parse a complicated string in C++ and create a tree from it. I would like to use C# in Visual Studio 2017 to call a native c++ method that returns a vector of nodes.
A Node looks like:
class node
{
public:
std::vector<node> subnodes;
std::string name;
};
and the c++ function might look like:
class noderizer
{
public:
node getNodes(std::string str);
};
what is the most efficient (coding time with secondary consideration for speed) way to call the noderizer::getNodes(...) member and create a equivalent class for c#?
I am assuming that the best route is to create a duplicate class definition in c# and then copy marshal the native std::strings into managed Strings"
public class node
{
public string name = string.Empty;
List<node> integers = new List<node>();
}
It's not clear if this article contains the latest information for c++ interop, but a related article on wrapping c++ native classes for use in c# indicates that I could most likely just wrap noderizer native c++ as noderizer * m_Impl; and then call the getNodes member and copy over each parameter. Is this the correct methodology?
You could use pInvoke as per your first referenced article, but the objects you are returning seem quite complicated. I think you will have a heck of a time with data marshalling if you're not already well versed (and even then). pInvoke is great for simple calls to C libraries where data marshalling is basic, but it gets very complicated very fast. This is not good for your situation.
The second article is closer to where you want to look. That being said, you have to consider whether you want to be wrapping a managed class or just calling a function that takes a string and returns your tree in managed format (i.e. it makes a copy rather than wrap unmanaged data). By your post it seems like you just need the latter.
Your best option is to use C++/CLI. Check out this tutorial. I am confident that taking this approach will make light work of your task. I won't attempt to explain the subject as the article above does a very good job. In essence, you will be able write functions with both managed and unmanaged data types, where all the data marshalling is built into the environment. A simple cast will marshal the data for you behind the scenes. As a big bonus, debugging is great as you can step from C# to C++/CLI to C++ code and back.
In the article above, the author does describe how to wrap an unmanaged class, which you can well do, but your problem will still be with data conversion.
I would approach your problem in 4 steps:
Write a static function getNodes() in C++/CLI that you can call from C# as any regular static method, passing a string as an argument. The article above will help you with that. Also See Here when creating the C++/CLI project.
getNodes() will use your C++ code to create a tree in its unmanaged form.
Use getNodes() to convert the tree from unmanaged to managed form.
Return the result to the caller in C#.
your declaration will look something like this, where the Node is your managed calss, ref keyword signifies that the class is managed, and ^ is the managed version of *.
public ref class noderizer
{
public:
static Node^ getNodes(String ^mStr);
};
Here getNodes() calls your C++ function and does the data conversion. I don't think it will take you long to figure it out.
Once you get a hang of the syntax, I think you will find it quite intuitive to use if you are already familiar with C# and C++.
As for performance, unless you're making thousands of consecutive calls or need critical real time data, it should not be an issue. One thing I would say though, if you're concerned with performance, you should write the pure C++ code in a separate purely unmanaged dll. I can't find the article for the life of me, but I remember looking at some benchmarks of executing purely unmanaged long running code block that was compiled inside the C++/CLI dll vs calling the exact same code that was compiled inside its own purely unmanaged dll. If I recall correctly, the separate dll was something like 3x faster.

Is it possible to call c# scripts from MATLAB?

I have a script in MATLAB that writes a CSV, the CSV is read by a c# script which writes a few more CSVs that I go back and read in MATLAB.
Is there any way to automate this so I don't have to call the c# code by hand each time?
It's very easy to call into .net from Matlab. The official documentation is at http://www.mathworks.co.uk/help/matlab/matlab_external/load-a-global-net-assembly.html You should be aware that Matlab is case-sensitive (even when it comes to specifying the assembly path) and that it is also limited in the kinds of objects it can pass back and forth across the boundary.
If you pass an array into your C# dll from Matlab, it will appear to be an array of bare objects rather than an array of numbers. In Matlab, you may need to use the char and cell methods to convert strings and arrays back into the form you are expecting.
To answer the title question, e.g. "Is it possible to call C# functions from MATLAB": yes, it is. Mathworks provides decent documentation on calling .NET assemblies from MATLAB on their website. Of course, there are limitations and some awkward quirks to take into account but basically you can create instances of .NET classes and interact with .NET applications from MATLAB.
To advise on automating this process, you could perhaps dive into the MATLAB COM Automation Service?
In the extension of this: it's also possible to call MATLAB functions in a .NET application. The other way around, sort of speak. This will be no problem with basic data types, but when it gets a bit more advances it can put you through some gnarly COM challenges, though.

Checking safety of Delphi DLL to use in C#

I have a DLL which takes care of custom drawing for some special glass effects. I'm putting it in a DLL for three reasons: 1) So it can be easily re-used and distributed of course without weighing its host app down, 2) So I can distribute it to developers without them knowing how it works, and 3) So it can be used from C#. It currently works in Delphi, but I know I will need to do many changes to make it support C#. For example, the main DLL function includes 1 parameter (a Record) which contains a number of types I know won't work in C# (like String, and maybe TColor). Project isn't quite 100% done yet, but is working.
I need someone to point out the easiest approach to accomplishing this. The code is too large to post it all here, so here it is at Pastebin.
Here's what I need to know:
Should I keep using Records as I am, or use something else like Packed Record?
Any tricks to use something other than String or PChar in these Records?
How would I wrap this DLL in C#? (I know very little C# by the way)
How to define equivalent records to pass to DLL function?
How to define equivalent constants in C#? (C# version of JDGlassCommon.pas)
How to get canvas handle (HDC) and parent handle (HWND) to send to DLL?
What would be equivalent to TColor?
Is it safe to pass types such as TColor in the Records?
Do you foresee any other issues in my code?
File List:
Library: JDGlassLib.dll *
Unit: JDGlassCommon.pas *
Package: JDLib.bpl
Unit: JDGlassCommon.pas *
Unit: JDGlass.pas *
Program: JDLibTestApplicationD7.exe
Form: JDLibTestAppD7.dfm *
Unit: JDLibTestAppD7.pas *
(* = code is included in above link)
(JDGlassCommon.pas is shared in both DLL and Component)
Should look something like this:
NOTE: I'm not asking for a re-write, although you're more than welcome to. I just need some tips on how to approach this.
PS: Original glass drawing code credited to "NGLN" of StackOverflow answering a prior question of mine: Delphi custom drawing - glowing glass
Should I keep using Records as I am, or use something else
like Packed Record?
Records are good for interop. Don't pack them, that just makes interop harder.
Any tricks to use something other than String or PChar in
these Records?
Don't use string. That's Delphi only and even specific to Delphi versions. PChar is fine for interop. Sometimes it can be simplest to use fixed length inline char arrays in records. It depends on the use.
How would I wrap this DLL in C#?
Call it from C# using p/invoke.
Is it safe to pass types such as TColor in the Records?
Yes that's easy to work with. Make sure it's a true RGB color rather than a special color like clWindow.
Do you foresee any other issues in my code?
The glass rendering may well be incompatible with the rendering used by the C# libraries. It could very well depend on whether or not your C# code uses WinForms or WPF. In fact you may well find that the C# developers would find it easier to use native C# code. I expect glass rendering is well supported in the common C# GUI frameworks.

tStringList passing in C# to Delphi DLL

I have a Delphi DLL with a function defined as:
function SubmitJobStringList(joblist: tStringList; var jobno: Integer): Integer;
I am calling this from C#. How do I declare the first parameter as a tStringList does not exist in C#. I currently have the declaration as:
[DllImport("opt7bja.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int SubmitJobStringList(string[] tStringList, ref int jobno);
But when I call it I get a memory access violation exception.
Anyone know how to pass to a tStringList correctly from C#?
You'll most likely not have any luck with this. The TStringList is more than just an array, it's a full-blown class, and the exact implementation details may differ from what is possible with .NET. Take a look at the Delphi VCL source code (that is, if you have it) and try to find out if you can rebuild the class in C#, and pass it with the help of your best friend, the Interop Marshaller. Note that even the Delphi string type is different from the .NET string type, and passing it without telling the marshaller what he should do, he will pass it as a char-array, most likely.
Other than that, I would suggest changing the Delphi DLL. It's never a good thing to expose anything Delphi-specific in a DLL that is to be used by non-Delphi clients. Make the parameter an array of PChar and you should be fine.
If this is your DLL, I'd rewrite the function to accept an array of strings instead. Avoid passing classes as DLL parameters.
Or, if you really want to use a TStringList for some reason, Delphi's VCL.Net can be used from any .Net language.
An old example using TIniFile: http://cc.codegear.com/Item/22691
The example uses .Net 1.1 in Delphi 2005. Delphi 2006 and 2007 support .Net 2.0.
If you don't control the DLL and they can't or won't change it, you could always write your own Delphi wrapper in a separate DLL with parameters that are more cross-language friendly.
Having a class as a parameter of a DLL function really is bad form.
I am not exactly clear your way of using delphi and C#. It seems you have created a Win32 DLL which you want to call from C#. Offcourse you must be using PInvoke for this.
I would suggest that you create a .NET DLL using your source code since complete porting of VCL is available. I can further elaborate if you wish....
In theory, you could do something like this by using pointers (casting them as the C# IntPtr type) instead of strongly typed object references (or perhaps wrapping them in some other type to avoid having to declare unsafe blocks), but the essential catch is this: The Delphi runtime must be the mechanism for allocating and deallocating memory for the objects. To that end, you must declare functions in your Delphi-compiled DLL which invoke the constructors and destructors for the TStringList class, you must make sure that your Delphi DLL uses the ShareMem unit, and you must take responsibility for incrementing and decrementing the reference count for your Delphi AnsiStrings before they leave the DLL and after they enter it, preferably also as functions exported from your Delphi DLL.
In short, it's a lot of work since you must juggle two memory managers in the same process (the .NET CLR and Delphi's allocators) and you must both manage the memory manually and "fool" the Delphi memory manager and runtime. Is there a particular reason you are bound to this setup? Could you describe the problem you are trying to solve at a higher level?
As Hemant Jangid said, you should easily be able to do this by compiling your code as a .NET dll and then referring to that assembly in your c# project.
Of course, you'll only be able to do this if the version of Delphi you have has Delphi.NET.
I don't know a lot about c#, but a technique that I use for transporting stringlists across contexts is using the .text property to get a string representing the list, then assigning that property on "the other side".
It's usually easier to get a string over the wall that it is a full blown object.

Categories