Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 [Все]   Вниз
  Печать  
Автор Тема: импорт функции, возвращающей список  (Прочитано 47381 раз)
0 Пользователей и 1 Гость смотрят эту тему.
remedius
Гость
« : 13-12-2006 10:51 » 

Здравствуйте!
Есть бибилотека, написанная на с++. В ней экспортируется функция, возвращающая список. Как получить список в приложении c#? (соответсвенно, какой тип данных должно иметь возвращаемой значение импортируемой функции?

extern "C" __declspec(dllexport) ... my_function() //функция должна возвращать список


[DllImport("My_LIBRARY.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern  ... my_function(); //функция, возвращающая список

Спасибо
« Последнее редактирование: 13-12-2006 10:59 от remedius » Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 13-12-2006 11:02 » 

Позвольте уточнить, что за список. Какой тип данных возвращается на С++?
Записан

ещё один вопрос ...
remedius
Гость
« Ответ #2 : 13-12-2006 11:03 » 

список структур (моих).
Записан
remedius
Гость
« Ответ #3 : 13-12-2006 11:05 » 

изначально был vector<>, но при экспорте данной функции, пришлось отказаться от шаблона с++. Теперь получается придется реализовывать свой список? если да, то все равно не совсем понятно, как потом его можно получить в приложении:(
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 13-12-2006 12:04 » 

предлагаю System.Object

[DllImport("My_LIBRARY.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern  System.Object my_function(); //функция, возвращающая список
« Последнее редактирование: 13-12-2006 12:06 от nikedeforest » Записан

ещё один вопрос ...
remedius
Гость
« Ответ #5 : 13-12-2006 12:05 » 

не поняла, а поподробнее можно рассказать?
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 13-12-2006 12:07 » 

Я выше немного подправил исправил
Записан

ещё один вопрос ...
remedius
Гость
« Ответ #7 : 13-12-2006 12:13 » 

Ок.
1.А возвращать из функции void*?
2. а что потом с object делать?
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 13-12-2006 12:28 » 

Я сразу говорю я сам этого никогда не делал, а пробовать есть большое желание, но раньше вечера пятницы я не смогу. Познания в .НЕТ у меня невелики, поэтому мои предположения. Если тебя это устраивает, то можно продолжить педполагать.
Возвращать надо не void*, а твой список,я бы для начала попробовал какой0нибудь простой класс.
Затем ты при вызове этой функции получишь объект класса System.Object. А вот дальше вообще труба, не особо мне верится, что ничего не предпринимая ты сожешь работать с этим объектом как с экземпляром класса. Но стоит попробовать. По ошибкам станет видно. Я не имею прао просить тебя пробовать, но самому очень интересно, поэтому в пятницу вечером обязательно попробую.
Записан

ещё один вопрос ...
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #9 : 13-12-2006 12:41 » 

список структур (моих).
Что значит список структур ? Массив ? Поподробнее плизз, иначе нормального ответа дождаться будет трудно.
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
remedius
Гость
« Ответ #10 : 13-12-2006 12:42 » 

массив или std::vector<my_struct>
Записан
remedius
Гость
« Ответ #11 : 13-12-2006 12:49 » 

Одно из решений:
Код:
[DllImport("My_library.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void GetGeometry(out MyStruct[] objs);

MyStruct[] gos;
 GetGeometry( out gos);
Код:
extern "C" __declspec(dllexport)void my_function( MyStruct** gos)
Записан
remedius
Гость
« Ответ #12 : 13-12-2006 12:51 » 

Да, а кто память то освободит? Улыбаюсь неужели это будет на совести фреймворка?
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 13-12-2006 12:53 » 

Ну раз Мороз пришел, значит дело заладится сейчас Улыбаюсь.
Записан

ещё один вопрос ...
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #14 : 13-12-2006 13:37 » 

Да, а кто память то освободит? Улыбаюсь неужели это будет на совести фреймворка?
Именно так. За освобождение памяти в фрэймворке отвечает GC ( Garbage Collector )
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
remedius
Гость
« Ответ #15 : 13-12-2006 13:39 » 

мм..так память выделялась в биллиотеке...

..
Я погорячилась. Предыдущий код не совсем верно работает. Длина возвращаемого массива всегда получается 1:(
Записан
remedius
Гость
« Ответ #16 : 13-12-2006 13:50 » 

Заработало:

Код:
[DllImport("My_library.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int GetGeometry(out MyStruct* objs);

MyStruct* gos;
 GetGeometry( out gos);
Код:
extern "C" __declspec(dllexport)int my_function( MyStruct** gos)
//но уже приходиться возвращать размер массива!!!
Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #17 : 13-12-2006 13:54 » 

мм..так память выделялась в биллиотеке...

Видимо я не совсем точно объяснил. Память используемую в managed dll фрэймворк не освободит.
Фрэймворк освобождает автоматически только свой ресурсы.
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
remedius
Гость
« Ответ #18 : 13-12-2006 13:56 » 

*наверно Вы имели ввиду в unmanaged ?
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 13-12-2006 13:57 » 

Я что-то не понял, вот это вот
Код:
MyStruct*
На С# катит?
Записан

ещё один вопрос ...
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #20 : 13-12-2006 13:58 » 

Посмотри ещё вот тута : http://msdn2.microsoft.com/en-gb/library/aa288468(VS.71).aspx
3-ий эгзампл Улыбаюсь Может чего прояснит Улыбаюсь
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #21 : 13-12-2006 14:00 » 

*наверно Вы имели ввиду в unmanaged ?
Ага Улыбаюсь Запареный сегодня я что-то Улыбаюсь
Я что-то не понял, вот это вот
Код:
MyStruct*
На С# катит?
Нет не катит.  Посмотри в сторону System.IntPtr
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemIntPtrClassTopic.asp
« Последнее редактирование: 13-12-2006 14:02 от MOPO3 » Записан

MCP, MCAD, MCTS:Win, MCTS:Web
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 13-12-2006 14:03 » 

Мороз, а нельзя никак было бы через System.Object?
Записан

ещё один вопрос ...
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #23 : 13-12-2006 14:04 » 

Я что-то не понял, вот это вот
Код:
MyStruct*
На С# катит?
Точнее катит, но только как : "Pointers may only be used in an unsafe context"
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #24 : 13-12-2006 14:11 » 

Мороз, а нельзя никак было бы через System.Object?
Сомневаюсь, но нужно тестить. Неизвестно что ты в итоге получиш в этот объект и сможеш ли кастить в нужную инфу.
Тут без эксперементоа что то сказать для меня трудновато Улыбаюсь
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
remedius
Гость
« Ответ #25 : 13-12-2006 14:18 » 

nikedeforest,  С Object у меня не получилось.
Записан
remedius
Гость
« Ответ #26 : 13-12-2006 14:19 » 

Возникла попутная проблема. Не получается передавать структуру:)
Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #27 : 14-12-2006 05:18 » 

Возникла попутная проблема. Не получается передавать структуру:)

Передать структуру из C# в unmanaged dll ?
Ну для этого надо сначала создать структуру на C#. Чтобы было реально её передать в  unmanaged функцию, необходимо использовать атрибут [StructLayout].

Вот пример :
Код:
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public class MySystemTime {
    public ushort wYear;
    public ushort wMonth;
    public ushort wDayOfWeek;
    public ushort wDay;
    public ushort wHour;
    public ushort wMinute;
    public ushort wSecond;
    public ushort wMilliseconds;
}
class Win32API {
    [DllImport("Kernel32.dll")]
    public static extern void GetSystemTime(MySystemTime st);
}

LayoutKind.Sequential - The members of the object are laid out sequentially, in the order in which they appear when exported to unmanaged memory.

Можно использовать : LayoutKind.Explicit - The precise position of each member of an object in unmanaged memory is explicitly controlled. Each member must use the FieldOffsetAttribute to indicate the position of that field within the type.

Вот пример :
Код:
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct Point {
    public int x;
    public int y;
}   

[StructLayout(LayoutKind.Explicit)]
public struct Rect {
    [FieldOffset(0)] public int left;
    [FieldOffset(4)] public int top;
    [FieldOffset(8)] public int right;
    [FieldOffset(12)] public int bottom;
}   

class Win32API {
    [DllImport("User32.dll")]
    public static extern bool PtInRect(ref Rect r, Point p);
}
« Последнее редактирование: 14-12-2006 05:25 от MOPO3 » Записан

MCP, MCAD, MCTS:Win, MCTS:Web
remedius
Гость
« Ответ #28 : 14-12-2006 07:05 » 

я делала что-то подобное, но у меня не удавалось передать структуру, где объявлены 2 string в структуре. (подряд, не подряд - без раазницы).
Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #29 : 14-12-2006 07:48 » 

я делала что-то подобное, но у меня не удавалось передать структуру, где объявлены 2 string в структуре. (подряд, не подряд - без раазницы).
А если вместо string использовать массив char[] (string.ToCharArray()) ?
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
remedius
Гость
« Ответ #30 : 14-12-2006 07:56 » 

что-то типа этого пробовала, там помниться проблема возникла вот в чем: перед такого рода полями надо писать     [MarshalAs(UnmanagedType...., SizeConst=LF_FACESIZE)](вот вместо ... я так ничего и не подобрала.

Вообще, в принципе, строки всегда можно одной строкой заменить:) (так я и поступила.
А если одна строка типа string в структуре, и перед ее объявлением указано  [MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)], то все работает...
ИМХО,  проблема возникает с выравниванием.

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

Такт что, Всем большое спасибо за помощь:)
Записан
remedius
Гость
« Ответ #31 : 14-12-2006 07:59 » 

P.S.  а вообще, когда передаешь в библиотеку, или получаешь переменные типа массивы (или подобные) Обязательно в аргументах, перед их объявлением надо не забывать [Out/In, MarshalAs(UnmanagedType.LPArray)] - к примеру
Записан
remedius
Гость
« Ответ #32 : 14-12-2006 07:59 » 

или [Out/In, MarshalAs(UnmanagedType...)] в зависимости от типа аргумента
Записан
remedius
Гость
« Ответ #33 : 14-12-2006 21:58 » 

Интересно, а если структура типа :
Код:
struct ObjectInfo
{
int color;
wchar_t name[32];
wchar_t description[150];
};
Так ли должна выглядеть структура на с#:
Код:
[StructLayout(LayoutKind.Explicit)]
public class ObjectInfo
{
[FieldOffset(0)]public int color;
[FieldOffset(4)]public string name;
[FieldOffset(68)]public string description;
};
Не понял
Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #34 : 15-12-2006 07:25 » 

Я бы пробовал сделать так :
[StructLayout(LayoutKind.Explicit)]
   public struct ObjectInfo
   {
      [FieldOffset(0)]public int color;
      [FieldOffset(4)]public char[32] name;
      [FieldOffset(68)]public char[150] description;
   };
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
remedius
Гость
« Ответ #35 : 15-12-2006 13:56 » 

Мммм.. как мне известно так:  [FieldOffset(4)]public char[32] name; C# не позволяет писать
Записан
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #36 : 15-12-2006 13:59 » 

Мммм.. как мне известно так:  [FieldOffset(4)]public char[32] name; C# не позволяет писать
Ага, сорри Улыбаюсь Зато вот так позволяет Улыбаюсь [FieldOffset(4)]public char[] name;
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
remedius
Гость
« Ответ #37 : 15-12-2006 14:00 » 

+ мне как-то не удавалось писать struct, т.к.
private static extern unsafe void GetNPointsForEachPart([Out, MarshalAs(UnmanagedType.LPStruct)] ObjectInfo oi,
Записан
remedius
Гость
« Ответ #38 : 15-12-2006 14:01 » 

программа вылетает, ругается что-то на маршлинг. В примере в мсдн class ключевое слово.
Записан
remedius
Гость
« Ответ #39 : 15-12-2006 14:03 » 

а если со словом class и с char[], то прога вываоливается с "Object reference not set to an instance of an object."
Записан
remedius
Гость
« Ответ #40 : 15-12-2006 14:04 » 

с class и с string ничего не валиться, но и значения для string не возвращаются.
Записан
remedius
Гость
« Ответ #41 : 15-12-2006 15:44 » 

а если со словом class и с char[], то прога вываоливается с "Object reference not set to an instance of an object."
А нет, извеняюсь, вылетает с ошибкой{"Mismatch has occurred between the runtime type of the array and the sub type recorded in the metadata." }
Записан
remedius
Гость
« Ответ #42 : 15-12-2006 16:03 » 

вот так получилось:
Код:
public class ObjectInfo
{

public int color;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=64)]
public char[] name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=300)]
public char[] description;
};

Но потом нужно самим вручную формировать строку. Во первых потому, что все символы через один 0, потом после двух 00(конец строки) лежит всякий мусор.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #43 : 15-12-2006 19:03 » 

Цитата: remedius
все символы через один 0
А символы, небось, латинского алфавита... В общем где-то появляется Unicode. Рекомендую поиграться с атрибутом "CharSet".
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
remedius
Гость
« Ответ #44 : 15-12-2006 19:07 » 

dimka,  это вполне объяснимо:
struct ObjectInfo
{
   int color;
   wchar_t name[32]; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   wchar_t description[150];//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
};
Записан
remedius
Гость
« Ответ #45 : 15-12-2006 19:10 » 

вообще я думаю так и должно быть. Ведь посылается фактически  массив. Вот в этот массив в функции dll тупо и копируются все символы. Ведь char[] не знает о завершающих симоволах!
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #46 : 15-12-2006 19:11 » 

Так какой смысл в исходной структуре объявлять wchar, когда приложение его не собирается читать?

Или приложение должно читать wchar? Тогда нужно уточнить кодировку.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
remedius
Гость
« Ответ #47 : 15-12-2006 19:12 » 

dimka, не совсем поняла о чем ты..воощем, клиенту посылается структура, поля которой wchar *.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #48 : 15-12-2006 19:15 » 

Цитата: remedius
Ведь char[] не знает о завершающих симоволах!
Я бы так сказал: тот механизм, который передаёт данные, совершенно справедливо не берётся полагать, что в wchar_t[] на самом деле хранится C-шная строка, а не что-то ещё (например, массив двухбайтовых целых со знаком).
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
remedius
Гость
« Ответ #49 : 15-12-2006 19:16 » 

ага. ты как всегда лучше говоришь:)
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #50 : 15-12-2006 19:16 » 

Цитата: remedius
поля которой wchar *.
Ничего подобного. Поля там wchar_t[N].
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
remedius
Гость
« Ответ #51 : 15-12-2006 19:23 » 

ну да. А что эт оменяет то? передаю я же UnmanagedType.ByValArray!
Записан
Страниц: 1 2 [Все]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines