I got a string which holds an entire definition of a C++ native struct (That means the ENTIRE struct - name, fields, enums but without methods in it, in the same syntax as you would simply write the struct on your own).
What I need to do is take the string and convert it to a string representing the Managed C++ type of the native type.
The parsing and handling of the string is done with C#.
I am looking for a way and a library perhaps which makes it easy to do what I need.
I was thinking of somehow create a template and edit it with the data from the given native struct.
If you got an answer please divide it into 2 cases - The case in which I DO NOT have access to the project/dll where the native struct itself is defined (which means it needs to be a pure parsing of the string) and to a case in which I do have access, in which I might be able to somehow use reflection?
In the end I used a T4 template. I made a template of a a managed C++ struct and parsed the native struct line be line and got the info needed about members and such and then inserted it to the T4 template.
Related
I know there is plenty of similar questions, but I want to understand very specific aspects that are never mentioned anywhere. In both cases: managed (NET runtime in this case) and native /unmanaged (c, cpp, etc)
Taken from here:
https://adamsitnik.com/Value-Types-vs-Reference-Types
The first issue that not just wasn't glossed over but not even mentioned is how your code/runtime supposed to know what type of struct you are dealing with? If struct is just all its data packed together, then where is metadata about what type of struct it is? Okay, may be in case of managed .NET runtime and binaries it is easier, it is part of the IL, but what about native binary code? It gets stripped 100%, if you open it for text reading there is no function or struct names in you binary. How would you know runtime what the struct you receive and how to treat/ parse it if there is no struct metadata with it? The pointer just points at memory, but there is no struct' structure and members there stored. At least class can be identified by extra data it has (object header and method table).
Things get even more confusing when you receive struct data from unmanaged/native space. You NEED to have that data embedded into struct otherwise how would you know what you receive? And I can't even begin to understand* how would this work for something like classes, because they are thousandfold more complex. How do you even return class from unmanaged space?
If struct is just all its data packed together, then where is metadata about what type of struct it is?
There isn't any. With raw value data - whether that means an individual value, or an array/vector/whatever, the consuming code is the thing that knows how to interpret it. What it is is just: bytes.
How would you know runtime what the struct you receive and how to treat/ parse it if there is no struct metadata with it?
Because it is defined in the API, either in a signature, or with human words such as "the pointer refers to the start of len elements of type Foo"
You NEED to have that data embedded into struct
No you don't; you just need to agree in advance what you are sending/receiving. This is how the vast majority of interactions between different codebases works, and has always worked. Having object metadata is the exception, not the norm.
How do you even return class from unmanaged space?
You wouldn't, if by "classes" in this context you mean managed objects.
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.
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).
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 :)
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.