I'm trying to understand managed/unmanaged code as it pertains to structs and classes. I have a struct with a property of another struct but its a pointer declaration as in:
struct StateInfo
{
Bitboard board;
StateInfo* previous;
}
I'm converting a C++ project to C#. Anyways, this doesn't work because Bitboard is a class. The error I get is something to the fact that pointers cannot be declared on managed types. If I take out Bitboard from the struct, it's fine. I need it though so I changed Bitboard from a class to a struct, and all is good. I'm not sure what's up? Any ideas?
You probably don't even want a struct. Instead:
class StateInfo
{
Bitboard board;
StateInfo previous;
}
In C#, a struct is a value type. For instance, int is a struct. They should typically be used for things which are entirely described by their value.
I suggest you read about blittability.
Blittable types have the same binary representation in managed and unmanaged code, and you need to represent them the same way if you want pointers to make sense.
Essentially, in c# all objects are automatically a pointer and do not need to be released.
Try reading some transitional articles about moving from C++ to C#
C++ -> C#: What You Need to Know to Move from C++ to C#
Related
Note: My question has several parts to it. I'd appreciate it if you would please answer each of the questions, instead of simply telling me what to do to get this to compile. :)
I'm not by any means good with C#. In fact, the reason why I don't know much about it is my class is focused on making efficient Algorithms and not really on teaching us .NET. Nevertheless all of our programs must be written in .NET and it hasn't been a problem until just now. I have the following code, but it won't compile and I don't really understand why. I have a gut feeling that this should be rewritten altogether, but before I do that, I want to know WHY this isn't allowed.
The point of the struct is to create a linked list like structure so I can add another node to the end of the "list" and then traverse and recall the nodes in reverse order
private struct BackPointer
{
public BackPointer previous;
public string a;
public string b;
public BackPointer(BackPointer p, string aa, string bb)
{
previous = p;
a = aa;
b = bb;
}
}
then later in my code I have something to the effect of
BackPointer pointer = new BackPointer();
pointer = new BackPointer(pointer, somestring_a, somestring_b);
The compile error I'm getting is Struct member 'MyClass.BackPointer.previous' of type 'MyClass.BackPointer' causes a cycle in the struct layout
This seems to be an obvious error. It doesn't like the fact that I am passing in the struct in the constructor of the same struct. But why is that not allowed? I would imagine this code would just create a new node in the list and return this node with a pointer back to the previous node, but apparently that's not what would happen. So what would actually happen then? Lastly what is the recommended way to resolve this? I was thinking to just tell it to be unmanaged just handle my pointers manually, but I only really know how to do that in C++. I don't really know what could go wrong in C#
That's not a pointer; it's an actual embedded struct value.
The whole point of structs is that they're (almost) never pointers.
You should use a class instead.
But why is that not allowed?
It's a struct - a value type. That means wherever you've got a variable of that type, that variable contains all the fields within the struct, directly inline. If something contains itself (or creates a more complicated cycle) then you clearly can't allocate enough space for it - because it's got to have enough space for all its fields and another copy of itself.
Lastly what is the recommended way to resolve this?
Write a class instead of a struct. Then the value of the variable will be a reference to an instance, not the data itself. That's how you get something close to "a pointer" in C#. (Pointers and references are different, mind you.)
I suggest you read my article on value types and reference types for more information - this is an absolutely critical topic to understand in C#.
Backpointer HAS to exist before creating a Backpointer, because you can't have a Backpointer without another Backpointer (which would then need another Backpointer and on and on). You simply can't create a Backpointer based on the way you've created it, because, as a struct, Backpointer can never be null.
In other words, it's impossible to create a Backpointer with this code. The compiler knows that, and so it forces you to make something that would work logically.
Structs are stored by value. In this case, your struct stores within itself another instance of the same struct. That struct stores within itself another struct and so on. Therefore this is impossible. It is like saying that every person in the world must have 1 child. There is no way this is possible.
What you need to use is a class. Classes store by reference, which means that it does not store the class within itself, it only stores a reference to that class.
A CLR struct is by definition a value type. What this means in your context is that the compiler needs to know the exact layout of the type. However, it cannot know how to layout a type which contains an instance of itself - does that sound reasonable? Change the struct to class (which makes your BackPointer to a reference type) and you'll see it's gonna work out of the box. The reason is that an instance of any reference type has always has the same layout - it is basically just a "pointer" to some location of the managed heap. I strongly recommend to read on a bit about the basics of C# or CLI type system.
I am developing a C# application. Since I have some algorithms for least-squares fit in C/C++ that would be too cumbersome too translate, I have made the C++ code into a dll and then created a wrapper in C#.
In the C# code, I have defined a struct that is passed to the unmanaged C++ code as a pointer. The struct contains the initial guesstimates for the fitting functions, and it is also used to return the results of the fit.
It appears to me that you must define the struct in both the managed and the unmanaged code. However, someone using my source code in in the future might decide to change the fields of the struct in the C# application, without understanding that they also have to change the struct in the native code. This will result in a run-time error at best (and produce erroneous results at worse), but there will be no error message telling the developer / end user what is wrong.
From my understanding, it impossible to create a test in the unmanaged C++ DLL that checks if the struct contains the correct fields, but is it posible to have the DLL returning a struct of the correct format to the C# wrapper?
Otherwise, what ways are there to reduce the risk that some careless programmer in the future causes run-time errors that are hard to detect?
Sample code:
//C++
struct InputOutputStruct {
double a,b,c;
}
extern "C" __declspec(dllexport) void DoSomethingToStruct(InputOutputStruct* s)
{
// ... algorithm
}
//C#
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct InputOutputStruct {
public double a,b,c;
}
[DllImport("CpluplusDll.dll")]
public static unsafe extern bool DoSomethingToStruct(InputOutputStruct* s);
class CSharpWrapper {
static void Main(string[] args)
{
InputOutputStruct s = new InputOutputStruct();
unsafe {
InputOutpustruct* sPtr = &s;
DoSomethingToStruct(sPtr);
s = *sPtr;
}
}
}
It appears to me that you must define the struct in both the managed
and the unmanaged code.
Not true. This is what C++/CLI was invented for- facilitate much easier interoperation with C++ and .NET.
but is it posible to have the DLL returning a struct of the correct format to the C# wrapper?
I don't think so, because you always need to define the structs on the C# side.
Here are a solution which may work ( never tested ):
Give each struct which is shared a unique identifier on both sides ( GUID, Macros )
Create a reflection for C++ which contains informations about the the types which are used on C# and C++ side. This could be done by using macros.
Compare the C++ structs and the C# structs on startup by using the GUIDs, reflection and macros. You can also use sizeof to compare sizes first.
That could be a lot of work
When working on C++ side you still can make a lot of things wrong when you not know about the macros
faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(
faacEncHandle hEncoder);
I'm trying to come up with a simple wrapper for this C++ library; I've never done more than very simple p/invoke interop before - like one function call with primitive arguments.
So, given the above C++ function, for example, what should I do to deal with the return type, and parameter?
FAACAPI is defined as: #define FAACAPI __stdcall
faacEncConfigurationPtr is defined:
typedef struct faacEncConfiguration
{
int version;
char *name;
char *copyright;
unsigned int mpegVersion;
unsigned long bitRate;
unsigned int inputFormat;
int shortctl;
psymodellist_t *psymodellist;
int channel_map[64];
} faacEncConfiguration, *faacEncConfigurationPtr;
AFAIK this means that the return type of the function is a reference to this struct?
And faacEncHandle is:
typedef struct {
unsigned int numChannels;
unsigned long sampleRate;
...
SR_INFO *srInfo;
double *sampleBuff[MAX_CHANNELS];
...
double *freqBuff[MAX_CHANNELS];
double *overlapBuff[MAX_CHANNELS];
double *msSpectrum[MAX_CHANNELS];
CoderInfo coderInfo[MAX_CHANNELS];
ChannelInfo channelInfo[MAX_CHANNELS];
PsyInfo psyInfo[MAX_CHANNELS];
GlobalPsyInfo gpsyInfo;
faacEncConfiguration config;
psymodel_t *psymodel;
/* quantizer specific config */
AACQuantCfg aacquantCfg;
/* FFT Tables */
FFT_Tables fft_tables;
int bitDiff;
} faacEncStruct, *faacEncHandle;
So within that struct we see a lot of other types... hmm.
Essentially, I'm trying to figure out how to deal with these types in my managed wrapper?
Do I need to create versions of these types/structs, in C#? Something like this:
[StructLayout(LayoutKind.Sequential)]
struct faacEncConfiguration
{
uint useTns;
ulong bitRate;
...
}
If so then can the runtime automatically "map" these objects onto eachother?
And, would I have to create these "mapped" types for all the types in these return types/parameter type hierarchies, all the way down until I get to all primitives?
I know this is a broad topic, any advice on getting up-to-speed quickly on what I need to learn to make this happen would be very much appreciated! Thanks!
Your are on the right track with how you would need to create managed structures that represent unamanged structures for use with P/Invoke.
It is however not the best strategy for interop with unmanaged libraries, because using this API from C# would still feel like using a C API - create and initialise a structure, pass it to a function and get some other structure in return.
It is OK to use P/Invoke for an odd function call that is not otherwise exposed as .NET API, but for a full blown API wrapper I would highly recommend using managed C++(C++/CLI). It is absolutely unparalleled in creating unmanaged interop layers for .NET.
The biggest challenge would be to convert this essentially C interface into an object orientated interface where you call methods off objects, as opposed to calling global functions with structures of all-public members.
As you start writing elaborate structure graphs for P/Invoke you would yourself having to deal with quite a bit of "magic" that governs how managed primitive types convert to unmanaged types. Often, using incorrect types will cause a run-time error.
With managed C++ (IJW - It Just Works) you define managed structures, classes, interfaces in C++, which allows more natural use of the underlying library and a more native interface to your C# application.
This is a great overview of C++/CLI. Also MSDN has extensive documentation for all managed C++ features.
Yes, you would need to declare all these structures in c#. Be careful to declare members with correct sizes. For example, 'long' is 32-bit in C++, but 64-bit in C#. For a pointer or void* in C++, use IntPtr in C#, etc.
In my C# application, I have a large struct (176 bytes) that is passed potentially a hundred thousand times per second to a function. This function then simply takes a pointer to the struct and passes the pointer to unmanaged code. Neither the function nor the unmanaged code will make any modifications to the struct.
My question is, should I pass the struct to the function by value or by reference? In this particular case, my guess is that passing by reference would be much faster than pushing 176 bytes onto the call stack, unless the JIT happens to recognize that the struct is never modified (my guess is it can't recognize this since the struct's address is passed to unmanaged code) and optimizes the code.
Since we're at it, let's also answer the more general case where the function does not pass the struct's pointer to unmanaged code, but instead performs some read-only operation on the contents of the struct. Would it be faster to pass the struct by reference? Would in this case the JIT recognize that the struct is never modified and thus optimize? Presumably it is not more efficient to pass a 1-byte struct by reference, but at what struct size does it become better to pass a struct by reference, if ever?
Thanks.
EDIT:
As pointed out below, it's also possible to create an "equivalent" class for regular use, and then use a struct when passing to unmanaged code. I see two options here:
1) Create a "wrapper" class that simply contains the struct, and then pin and pass a pointer to the struct to the unmanaged code when necessary. A potential issue I see is that pinning has its own performance consequences.
2) Create an equivalent class whose fields are copied to the struct when the struct is needed. But copying would take a lot of time and seems to me to defeat the point of passing by reference in the first place.
EDIT:
As mentioned a couple times below, I could certainly just measure the performance of each of these methods. I will do this and post the results. However, I am still interested in seeing people's answers and reasonings from an intellectual perspective.
I did some very informal profiling, and the results indicate that, for my particular application, there is a modest performance gain for passing by reference. For by-value I got about 10,050,000 calls per second, whereas for by-reference I got about 11,200,000 calls per second.
Your mileage may vary.
Before you ask whether or not you should pass the struct by reference, you should ask yourself why you've got such an enormous struct in the first place. Does it really need to be a struct? If you need to use a struct at some point for P/Invoke, would it be worth having a struct just for that, and then the equivalent class elsewhere?
A struct that big is very, very unusual...
See the Design Guidelines for Developing Class Libraries section on Choosing Between Classes and Structures for more guidance on this.
The only way you can get an answer to this question is to code up both and measure the performance.
You mention unmanaged/managed interop. My experience is that it takes a surprisingly long time to to the interop. You could try changing your code from:
void ManagedMethod(MyStruct[] items) {
foreach (var item in items) {
unmanagedHandle.ProcessOne(item);
}
}
To:
void ManagedMethod(MyStruct[] items) {
unmanagedHandle.ProcessMany(items, items.Count);
}
This technique helped me in a similar case, but only measurements will tell you if it works for your case.
Why not just use a class instead, and pass your class to your P/Invoke function?
Using class will pass nicely around in your managed code, and will work the same as passing a struct by reference to a P/Invoke function.
e.g.
// What you have
public struct X
{
public int data;
}
[DllImport("mylib.dll")]
static extern void Foo( ref X arg);
// What you could do
[StructLayout(LayoutKind.Sequential)]
public class Y
{
public int data;
}
[DllImport("mylib.dll")]
static extern void Bar( Y arg );
I have a structure that represents a wire format packet. In this structure is an array of other structures. I have generic code that handles this very nicely for most cases but this array of structures case is throwing the marshaller for a loop.
Unsafe code is a no go since I can't get a pointer to a struct with an array (argh!).
I can see from this codeproject article that there is a very nice, generic approach involving C++/CLI that goes something like...
public ref class Reader abstract sealed
{
public:
generic <typename T> where T : value class
static T Read(array<System::Byte>^ data)
{
T value;
pin_ptr<System::Byte> src = &data[0];
pin_ptr<T> dst = &value;
memcpy((void*)dst, (void*)src,
/*System::Runtime::InteropServices::Marshal::SizeOf(T::typeid)*/
sizeof(T));
return value;
}
};
Now if just had the structure -> byte array / writer version I'd be set! Thanks in advance!
Using memcpy to copy an array of bytes to a structure is extremely dangerous if you are not controlling the byte packing of the structure. It is safer to marshall and unmarshall a structure one field at a time. Of course you will lose the generic feature of the sample code you have given.
To answer your real question though (and consider this pseudo code):
public ref class Writer abstract sealed
{
public:
generic <typename T> where T : value class
static System::Byte[] Write(T value)
{
System::Byte buffer[] = new System::Byte[sizeof(T)]; // this syntax is probably wrong.
pin_ptr<System::Byte> dst = &buffer[0];
pin_ptr<T> src = &value;
memcpy((void*)dst, (void*)src,
/*System::Runtime::InteropServices::Marshal::SizeOf(T::typeid)*/
sizeof(T));
return buffer;
}
};
This is probably not the right way to go. CLR is allowed to add padding, reorder the items and alter the way it's stored in memory.
If you want to do this, be sure to add [System.Runtime.InteropServices.StructLayout] attribute to force a specific memory layout for the structure. In general, I suggest you not to mess with memory layout of .NET types.
Unsafe code can be made to do this, actually. See my post on reading structs from disk: Reading arrays from files in C# without extra copy.
Not altering the structure is certainly sound advice. I use liberal amounts of StructLayout attributes to specify the packing, layout and character encoding. Everything flows just fine.
My issue is just that I need a performant and preferably generic solution. Performance because this is a server application and generic for elegance. If you look at the codeproject link you'll see that the StructureToPtr and PtrToStructure methods perform on the order of 20 times slower than a simple unsafe pointer cast. This is one of those areas where unsafe code is full of win. C# will only let you have pointers to primitives (and it's not generic - can't get a pointer to a generic), so that's why CLI.
Thanks for the psuedocode grieve, I'll see if it gets the job done and report back.
Am I missing something? Why not create a new array of the same size and initialise each element seperately in a loop?
Using an array of byte data is quite dangerous unless you are targetting one platform only... for example your method doesn't consider differing endianness between the source and destination arrays.
Something I don't really understand about your question as well is why having an array as a member in your class is causing a problem. If the class comes from a .NET language you should have no issues, otherwise, you should be able to take the pointer in unsafe code and initialise a new array by going through the elements pointed at one by one (with unsafe code) and adding them to it.