2012-05-24 3 views
1

У меня есть структура C++, которая имеет char [20], как показано ниже, и она упакована.char [] эквивалент массива в C#

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

Теперь, как я могу написать эту структуру в C#, чтобы обе были одинаковыми. я написал, как это в 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; 
} 

ниже декларация PInvoke в C#

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

с функцией ++, которая вызывает эту структуру в качестве параметра

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); 
} 

, но когда я делаю, как это в C# он дает мне ненужные данные в C++, когда я присваиваю значения для них в C#. Может ли кто-нибудь помочь.

Спасибо всем за помощь по вышеуказанному, но теперь у меня есть новая проблема, которая является продолжением этого, я предоставляю все подробно ниже.

Мои структуры в 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) 

я написал эквивалентные C# Структуры, как этот

[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; 
} 

ниже моего C# PInvoke

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

ниже мой с методом ++, который вызывает-структуру в качестве параметра

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); 
} 

Теперь проблема заключается в том, что у меня есть структурная переменная m_type (struct "type"), объявленная в struct temp, переменные, объявленные ранее (long req), которые хорошо печатаются в моей программе на C++, но объявленная переменная после этого не дают мне выхода. Так что, я думаю, что объявление структур в C# испортилось, и я не могу понять это, поэтому любой может помочь.

+3

Я думаю, вы хотите байт [20]. – Ben

+0

@Ben 'byte [20]' не компилируется в C#. –

+0

@ DavidHeffernan - я представил все подробно сейчас – krishna555

ответ

1

Вы объявили структуру как класс в C#. Это нормально, но это означает, что любая переменная этого типа уже является ссылкой. Поэтому вам не нужно проходить мимо ref. Когда вы передаете класс по ссылке, вы заканчиваете передачу указателя на указатель на объект. Это один уровень косвенности слишком много.

P/вызова в коде C# поэтому должно быть так:

public static extern int OrderRequirement(temp tmp); 

Другой способ исправить это оставить ref в объявлении функции, но объявить temp типа как struct а не class. Это потому, что struct является типом значения. Переменной, тип которой является struct, является значение, а не ссылка.

Оба решения работают, это зависит от вас, которое вы выбираете.

В коде на C++ есть еще одна проблема.

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

Вы передаете p и q, которые имеют тип std::string к printf и ожидает строку формата %s напечатать их. Это ошибка. Вам нужно позвонить c_str() по строкам. Как это:

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

Проблема с обновлением в том, что долго 32 бита Windows, C++ и 64 бита в C#. Вы должны объявить его как int в C#. И вы вообще пропустили поле id.

[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; 
} 
+0

Я попробовал то, что вы упомянули изначально, я думал, что это сработало, но оно не работает. – krishna555

+1

Да, это действительно работает. Я построил DLL, чтобы доказать, что он работает. Возможно, вы можете показать, что у вас есть сейчас, и я могу помочь, но я уверен, что это работает. И когда вы говорите «это не работает», мы не можем с этим многое сделать. Вам нужно предоставить детали. Каким образом ваш код не работает. –

+0

ok Я дважды проверил его и его работу, я проверил его, добавив к нему другую структуру, и я вижу исходную проблему. Структура с другой структурой вызывает проблемы, и я не знаю, как ее исправить. я отредактировал мой код с новой проблемой, вы можете взглянуть на него. – krishna555

Смежные вопросы