Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Как создать массив и вернуть ссылку на него?


Автор: vlsaf 18.4.2014, 08:37
Программа, написанная на С# вызывает функцию из прилинкованной dll-ки. Как-то так
Код

private static extern void MyFunk([Out] out double[] A);

Т.е. заранее размерность массива А не известна. Программа на С++ сама его создает и той размерности, которой сочтет нужным.
Сигнатура функции на С++ очень простая
Код

int MyFunk(double *A)


Функция на С++ должна создать одномерный массив А размерностью N и вернуть его  в вызывающую функцию на C#.

Подскажите, как это сделать?

Автор: borisbn 18.4.2014, 08:50
Есть подозрение, что это не получится. Никак. Массив в до-диезе это не просто указатель как в Си++.
И в любом случае в функцию на Си нужно передавать указатель на указатель.

Автор: vlsaf 18.4.2014, 09:12
Может я не правильно написал сигнатуру функции?
Может ее надо как-то по другому писать?

Вопрос остается тот-же, как написать на С++ функцию, чтобы она возвращала массив в С# 

Автор: borisbn 18.4.2014, 12:42
Код
extern static public int MyFunk( out IntPtr result );
...
IntPtr ptr;
int size = MyFunk( ptr );
int[] managedArray = new int;
Marshal.Copy( ptr, managedArray, 0, size );

Код
int MyFunk( int ** p ) {
    int N = 42;
    *p = new int[ N ];
    return N;
}

Может быть как-то так получится... Не проверял

Автор: Guinness 18.4.2014, 12:57
Цитата(borisbn @  18.4.2014,  13:42 Найти цитируемый пост)
Не проверял

Там вроде managed C++ нужно использовать. М.б. с gcnew взлетит.

Автор: vlsaf 18.4.2014, 14:17
Цитата(borisbn @ 18.4.2014,  12:42)
Может быть как-то так получится... Не проверял

Оно наверняка получится, но если использовать Marshal.Copy, то при достаточном частом обращении к функции и большому объему копируемой матрицы, будет тратиться заметное время. Нужно разместить возвращанмую матрицу в памяти, доступной для C# кода, чтобы не копировать. В другом форуме подсказали использовать выдение памяти в С++ либо через GlobalAlloc либо через CoTaskMemAlloc. Пока не знаю как это все должно крутиться :(

Автор: DarthTon 18.4.2014, 15:27
Код

int MyFunk( array<double>^% result )
{
    int N = 42;
    result = gcnew array<double>( N );    // allocate double[] array
    return N;
}

Компилить с /clr.

Автор: vlsaf 18.4.2014, 17:25
Спасибо. В понедельник попробую. 

Понимаю так, что dll уже надо засовывать в C# проекте, 
как обычно, в reference (т.е. это уже управляемый код)? 
ImportDll уже не нужен. 

Сигнатура вызова этой функции из C# уже обычная?
Код

var n = MyFunk(out A);

Автор: vlsaf 21.4.2014, 09:42
Попробывал. Код на C# подцепил управляемую сборку. Увидел функцию MyFunk, но студия определила сигнатуру вот так:
Код

int MyFunk(ref double[] А);


Этого мне нужно было избежать, т.к. ref нужно заранее инициализировать.

Автор: Guinness 21.4.2014, 09:51
http://stackoverflow.com/questions/3514237/ref-and-out-in-c-cli

Автор: vlsaf 21.4.2014, 10:34
Guinness, супер!

на плюсах нужен был параметр [Оut]

Код

double[] A;


Потом вызываю функцию:
Код

var err = MyFunk(out A);


Все идет на ура! Массив А становится размером такой, как нужно!!!

Всем спасибо за подсказки.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)