1

i have a c++ struct which has char[20] like below, and it is packed.

#pragma pack(push, temp_aion_packed, 1)
struct temp
{
  char x[20];
  char y[20];
};
#pragma pack(pop, temp_aion_packed)

now how can i write this struct in c# so that both are same. i have written like this in c#

[DataContract]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1),Serializable]
public class temp
{
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
     public string x;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
     public string y;
}

below is the pinvoke declaration in c#

[DllImport("rmsCAPI.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, EntryPoint = "OrderRequirement")]
    public static extern int OrderRequirement(ref temp tmp);

c++ function that calls this struct as parameter

long __stdcall OrderRequirement(struct temp *tmp)
{
  string p="";
  string q="";
  p=temp->x;
  q=temp->y;
  char buff[2048];
  sprintf(buff,"p: %s\n q: %s\n x: %s\n y: %s\n",p,q,temp->x,temp->y);
 }

but when i do like this in c# it is giving me the junk data in c++, when i assign values for them in c#. Can any one please assist.

Thank you all for help on the above one, but now i got a new problem which is an extension of this, i am providing everything in detail below.

My structures in c++

#pragma pack(push, temp_aion_packed, 1)
struct temp
{
  long req;
  struct type m_type;
  short id;
  char x[20];
  char y[20];
};
#pragma pack(pop, temp_aion_packed)

#pragma pack(push, type_aion_packed, 1)
struct type
{
  short i;
};
#pragma pack(pop, type_aion_packed)

i have written equivalent c# structs like this

[DataContract]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1),Serializable]
public struct temp
{
   [DataMember]
    public long req;
   [DataMember]
    [MarshalAs(UnmanagedType.Struct)]
     public type m_type;
   [DataMember]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
     public string x;
   [DataMember]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
     public string y;
}

[DataContract]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1),Serializable]
public struct type
{
  [DataMember]
    public short i;
}

below is my c# pinvoke

[DllImport("rmsCAPI.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, EntryPoint = "OrderRequirement")]
    public static extern int OrderRequirement(ref temp tmp);

below is my c++ method that calls struct as parameter

long __stdcall OrderRequirement(struct temp *tmp)
{
  char buff[2048];
  sprintf(buff,"req: %ld \n id: %d \n x: %s\n",tmp->req,tmp->id,tmp->x);
}

now the problem i am getting is as i have structure variable m_type(of struct "type") declared in struct temp, the variables declared before (long req)that are printing fine in my c++ program but the variable declared after that are not giving me any output. So i think the declaration of structures in c# is messing up and i am unable to figure it out so can any one please help.

3
  • @Ben byte[20] does not compile in C#. Commented May 24, 2012 at 15:14
  • @DavidHeffernan -- i provided everything in detail now Commented May 24, 2012 at 15:41
  • Thank you for that. I'm confident that I have the solution for you now. See my answer. Commented May 24, 2012 at 16:23

1 Answer 1

1

You declared the struct as a class in C#. That's fine, but it means that any variable of that type is already a reference. So you don't need to pass by ref. When you pass a class by ref you end up passing a pointer to a pointer to the object. That's one level of indirection too many.

The P/invoke in the C# code should therefore be like this:

public static extern int OrderRequirement(temp tmp);

The other way to fix it is to leave the ref in the function declaration, but to declare the temp type as a struct rather than a class. That's because a struct is a value type. A variable whose type is a struct is a value rather than a reference.

Both solutions work, it's up to you which you choose.


There is another problem in your C++ code.

sprintf(buff,"p: %s\n q: %s\n x: %s\n y: %s\n",p,q,temp->x,temp->y);

You are passing p and q, which are of type std::string to printf and expecting the %s format string to print them. That's an error. You need to call c_str() on the strings. Like this:

sprintf(
  buff,
  "p: %s\n q: %s\n x: %s\n y: %s\n",
  p.c_str(),q.c_str(),temp->x,temp->y
);

The problem with your update is that long is 32 bits in Windows C++ and 64 bits in C#. You need to declare it as int in C#. And you missed the id field altogether.

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1),Serializable]
public struct temp
{
    [DataMember]
    public int req;

    [DataMember]
    public type m_type;

    [DataMember]
    public short id;

    [DataMember]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
    public string x;

    [DataMember]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
    public string y;
}
Sign up to request clarification or add additional context in comments.

6 Comments

i tried what you mentioned initially i thought it worked but it is not working.
Yes it does work. I built a DLL to prove that it works. Perhaps you can show what you have now and I can help, but I'm sure this works. And when you say "it is not working", we can't do much with that. You need to supply details. In precisely what way is your code failing.
ok i double checked it and its working i verified it by adding another structure to it, and i see the original problem. Structure with in another structure is what causing the problem and i don't no how to fix it. i have edited my code with the new problem can you take a look at it.
That's a completely different question. I answered it anyway, but next time please ask a new question. One question at a time is the rule here.
@David-- so what is equivalent of int in c++ to c#?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.