1) Как в эту экспортируемую функцию в качестве первого параметра передать NULL ?
Чтобы было эквиваленто С++ вызову: SomeFunct(NULL, &ulSize);
Компилер хочет видеть именно указатель на структуру, а не NULL
2) Есди я правильно понял я могу выделить массив структур так:
SERVER_STRUCT[xxx] pServers = new SERVER_STRUCT[xxx];
Правильно ли организован вызов функции в этом случае?
Хочу передать начало этого массива в функцию чтобы она его заполнила.
SomeFunct(ref pServers[0], ref ulSize);
Компилер компилит, но логично ли это стилю C# ?
Прошу сильно не пинать. С# в глаза вижу первые 2 часа. Поиск пробовал, но конкрнетно на свои вопросы — ответов не нашел.
Здравствуйте, _f_b_i_, Вы писали:
___>>Клиент хочет рабочий пример на C#, а в виду того что програмированием на С# не занимался — возникли затруднения. ___>>Есть экспортируемая из DLL функция int SomeFunct(struct SERVER_STRUCT *lpServers, unsigned int *lpInt); ___>>В эквиваленте на С# получил следующее: [c#]
[/c#] ___>>Возникло 2 вопроса: ___>>1) Как в эту экспортируемую функцию в качестве первого параметра передать NULL ? ___>> Чтобы было эквиваленто С++ вызову: SomeFunct(NULL, &ulSize); ___>> Компилер хочет видеть именно указатель на структуру, а не NULL
Объявить, вдобавок к основному определению, и так:
[DllImport("some.dll")]
public static extern Int32 SomeFunc(IntPtr pServers, IntPtr pulSize);
И вызывать с IntPtr.Zero.
___>>2) Есди я правильно понял я могу выделить массив структур так: ___>> SERVER_STRUCT[xxx] pServers = new SERVER_STRUCT[xxx]; ___>> Правильно ли организован вызов функции в этом случае? ___>> Хочу передать начало этого массива в функцию чтобы она его заполнила. ___>> SomeFunct(ref pServers[0], ref ulSize); ___>> Компилер компилит, но логично ли это стилю C# ? ___>>Прошу сильно не пинать. С# в глаза вижу первые 2 часа. Поиск пробовал, но конкрнетно на свои вопросы — ответов не нашел.
В первом параметрe ожидается массив? Надо посмотреть описание структуры SERVER_STRUCT.
Help will always be given at Hogwarts to those who ask for it.
Спасибо, не сообразил что может быть два определения к одному импорту.
_FR>В первом параметрe ожидается массив? Надо посмотреть описание структуры SERVER_STRUCT.
В первом параметре ожидается указатель на структуру. Обычный блок памяти который заполняется
структурными данными. Данных может быть много, поэтому выделяю блок памяти, столько — сколько
нужно и передаю указатель в фунцию. Собственно так делаю на С. Библиотечкая функция осталась,
а реализацию вызова нужно сделать на на C#.
Структура на С приблизительно такая:
typedef struct _SERVER_STRUCT
{
unsigned int ...;
unsigned int ...;
....
char cName[256];
} SERVER_STRUCT;
Превратил в аналог:
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct SERVER_STRUCT
{
public UInt32 ...;
public UInt32 ...;
...
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] cName;
}
Здравствуйте, _f_b_i_, Вы писали:
_FR>>В первом параметрe ожидается массив? Надо посмотреть описание структуры SERVER_STRUCT. ___>В первом параметре ожидается указатель на структуру.
Тогда всё нормально,
SomeFunct(ref pServers[0], ref ulSize);
вполне логично.
Единственно, если SomeFunct меняет что-то в переданной структуре более правильным будет указать [ Out ] перед параметром в объявлении:
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, _f_b_i_, Вы писали:
_FR>Единственно, если SomeFunct меняет что-то в переданной структуре более правильным будет указать [ Out ] перед параметром в объявлении: _FR>
Если память под массив вы выделяете на дотнетной стороне и SomeFunc об этом знает и не меняет переданный ей указатель и не пишит по нему чего не попадя (структуры изменять — законно), то это корректно.
Help will always be given at Hogwarts to those who ask for it.
_FR>Если память под массив вы выделяете на дотнетной стороне и SomeFunc об этом знает и не меняет переданный ей указатель и не пишит по нему чего не попадя (структуры изменять — законно), то это корректно.
Да выделяю память вот так:
pServers = new SERVER_STRUCT[nServerCount];
Функция в DLL не знает кто и где выделил ей память (но полагаю что на C# выделяется из стандартной кучи процесса), все что она знает это указатель на начало памяти и ее размер.
Собствено функция в DLL только лишь заполняет структуры данных:
Здравствуйте, _f_b_i_, Вы писали:
___>Да выделяю память вот так: ___>pServers = new SERVER_STRUCT[nServerCount];
___>Функция в DLL не знает кто и где выделил ей память (но полагаю что на C# выделяется из стандартной кучи процесса), все что она знает это указатель на начало памяти и ее размер. ___>Собствено функция в DLL только лишь заполняет структуры данных:
Тогда всё должно быть в порядке.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Тогда всё должно быть в порядке.
А еще быстрый вопрос. у меня в структуре объявлен элемент:
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] cName;
Который правильно заполняется. Хочу преобразовать его в String (хотя меня как программера устроило бы и как есть, но
подозреваю что товаришь программист С# заказчика, будет доставать как конвертировать в его любимый String)
делаю приблизительно следующее:
string s = new string(pServers[i].cName);
Все хорошо, но раздражает куча нулей, которые остались от char[] cName.
Сразу возник вопрос — разве не должен был конструктор стринга отрезать стринг как только встретил первый /0 ?
Здравствуйте, _f_b_i_, Вы писали:
_FR>>Тогда всё должно быть в порядке. ___>А еще быстрый вопрос. у меня в структуре объявлен элемент:
___>[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
___> public char[] cName;
___>Который правильно заполняется. Хочу преобразовать его в String (хотя меня как программера устроило бы и как есть, но ___>подозреваю что товаришь программист С# заказчика, будет доставать как конвертировать в его любимый String)
___>делаю приблизительно следующее: ___>string s = new string(pServers[i].cName); ___>Все хорошо, но раздражает куча нулей, которые остались от char[] cName. ___>Сразу возник вопрос — разве не должен был конструктор стринга отрезать стринг как только встретил первый /0 ?
Вряд ли — а с какой стати? В спеке про это ни слова.
Можно так:
var s1 = new string(pServers[i].cName).TrimEnd('\0');
var s2 = new string(pServers[i].cName, 0, 1 + Array.FindLastIndex(pServers[i].cName, ch => ch != 0));