How to pass an array of structs from c++ to c#? - 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.

Related

How to share primitive data between C# and C++?

Let's say I have some int sharedInt that I need to share between managed C# code and a native C++ library. Both the C# and C++ code need to be able to read and write from/to sharedInt.
My first solution was to allocate memory from C# using Marshal.AllocHGlobal(), pass the IntPtr to the C++ library as an int*, and read/write to it using Marshal.ReadInt32() and Marshal.WriteInt32(). This worked, but the constant Marshal calls slowed my application quite a bit.
My second solution was to simply declare the int from C#, pass it as a ref int to the C++ library, and read/write from it directly. This works for the first few calls, and then behaves unpredictably, often throwing an ExecutionEngineException. Maybe the garbage collector is at fault?
How do I accomplish my goals? How do references to value types work in C#? Do I need to create some wrapper structure, and how do I properly pass it to C++?

What is the equivalent of Type Statement from VBA in C#?

What is the equivalent of Type from VBA in C#?
I am asking, because I have some code in Excel which I am trying to turn into a standalone C# application. I have a function, which comes from a .dll, which takes in a Type with some strings and longs as an argument. How would I replicate this in C#? Will this even work, or the will the function from .dll not even work in C#?
I haven't yet experimented with this, because it is all connected to a working database, and I want to know how this would work before I mess something up.
You say that you use a Type in VBA to pass data to a function contained in some DLL. Seeing some code would help, but this technique is usually used to call a (Windows API or third-party) DLL expecting some C-type struct.
In C#, you would use P/Invoke to call functions in unmanaged DLLs, and you would typically use a struct for complex types required by the DLL. Using a class is also possible, but there are some subtleties to be aware of.
A simple example can be found in this SO answer:
https://stackoverflow.com/a/47429104/87698
If your DLL is part of the Windows API, you can use http://pinvoke.net/ to find ready-to-use C# declarations for the functions as well as the data structures.
The example in the linked documentation would be rewritten as:
struct StateData
{
int[] CityCode;
string County;
}
var Washington = new StateData[100];
Although at some point you'd have to initialize CityCode. In VBA you could do it implicitly but in c# you'd have to write something like:
foreach (var w in Washington) w.CityCode = new int[100];
The closest will be the Struct datatype. It is similar in that it is a user-defined data type containing one or more elements (members) of various data types, and these elements are accessed as fields of the Type/Struct.
Both are values types and use stack allocation (usually).

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.

c++ structure pointer cast as array interop 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

Passing a structure of data from VC++ to C#?

I want to transfer a structure of data to an application which is created in C#.
I will be filling the structure in a VC++ program.
How can I send it?
Is structure suppported in C#?
Or else if I use LPDATA in VC++: how can I get the same thing in C#?
Defining the struct in C#
When defining your struct in C# make sure you use datatypes which match the C++ implementations. Char in C++ as Byte in C# etc...
You need to add some attributes to ensure your struct memory layout in C# matches the C++ implementation
[StructLayout(LayoutKind.Sequential, Size=TotalBytesInStruct),Serializable]
public struct MyStruct
{
}
Passing the struct
Declare a struct in C# using the same data structure. Pass a pointer to the struct to your C# app from C++ and cast it to the new struct in C#.
Calling you C# dll
For calling your C# DLL, your best option is to use a mixed mode assembly in C++. This allows you to use the pragmas managed and unmanaged to switch between native and managed code. This way you can nicely wrap you C# class with a workable C++ wrapper. See this Microsoft article. Be aware though, this is not supported on Mono.
Yes, structure is supported and can be used. Strings may require a bit of work, however.
Show us your structure. C# has marshaller helpers to map its types to native c++ types easily, you just have to know how to decorate your types, and we can help with that if you show us your structure.
For example, that LPDATA thing you mentioned, if that's char *, it maps directly over byte[] in C# if it's a generic buffer, or string if it's a normal string (the string mapping requires marshaller help, but it's a lot easier to use once decorated properly).
You could learn a lot from the "platform invoke tutorial" on MSDN.
The only difference is that you'll be invoking your own DLL :)

Categories