powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Создание одномерного массива типа double размерности N
25 сообщений из 33, страница 1 из 2
Создание одномерного массива типа double размерности N
    #38618331
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Программа, написанная на С# вызывает функцию из прилинкованной dll-ки, написанной на C++. Как-то так
Код: c#
1.
private static extern void MyFunk([Out] out double[] A);


Т.е. заранее размерность массива А не известна. Программа на С++ сама его создает и той размерности, которой сочтет нужным.
Сигнатура функции на С++ очень простая
Код: plaintext
1.
int MyFunk(double *A)



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

Подскажите, как это сделать?
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38618341
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsaf,

Я полагаю, это -- вопрос по C# и его API для взаимодействия с программами на С.

Предлагаю перенести тему у форум по C#.
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38618352
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кто-же на С# напишет пример программы на С++?
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38618374
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может я не правильно написал сигнатуру функции?
Может ее надо как-то по другому писать?

Вопрос остается тот-же, как написать на С++ функцию, чтобы она возвращала массив в С#
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38618442
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsafВопрос остается тот-же, как написать на С++ функцию, чтобы она возвращала массив в С#
вопрос скорее - как принять результат.
память выделить либо GlobalAlloc либо CoTaskMemAlloc

в c# принять как [out]IntPtr - самый простой вариант

освобождать память в c# Marshal.FreeHGlobal или Marshal.FreeCoTaskMem соответсвенно
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38618538
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилпамять выделить либо GlobalAlloc либо CoTaskMemAlloc
Выделение памяти должно идти где? В С++?
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38618609
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsafИзопропилпамять выделить либо GlobalAlloc либо CoTaskMemAlloc
Выделение памяти должно идти где? В С++?

да

ЗЫ почему void? (private static extern void MyFunk)
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38618714
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это я ошибся при написании.

Как должна выглядеть сигнатура функции на С++? Так же, как я написал?
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619056
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsafЭто я ошибся при написании.

Как должна выглядеть сигнатура функции на С++? Так же, как я написал?
лучше так -
Код: plaintext
1.
extern  "C" __declspec(dllexport) void __stdcall   MyFunc(int*, double ** );



результирующий размер лучше через параметр вернуть, маршаллинг проще получится, если потребуется скопировать массив в c#
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619134
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделал. Сенкс. Но!
Marshal.Copy на массиве double размерностью 10 000 000 идет 75 ms. Дофига.
Что-то есть в природе такое, чтобы не копировать, а пользоваться той памятью, в которую С++ записало матрицу?
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619157
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsafЧто-то есть в природе такое, чтобы не копировать, а пользоваться той памятью, в которую С++ записало матрицу?

unsafe код - работа с указателями в c#
или выделение памяти в c# и передача указателя в C++

PS вариант без c# - рассматривался?
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619732
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Работа без C# не рассматривается.
Выделение памяти в c# и передача указателя в C++ тоже отпадает, т.к. заранее неизвестно, сколько памяти выделять.

unsafe код + fixed, думал над этим, но так и не придумал, как правильно это сделать.
На стороннем форуме посоветовали следующее:
Код: plaintext
1.
2.
3.
4.
5.
6.
int MyFunk( array<double>^% result )
{
    int N = 42;
    result = gcnew array<double>( N );    // allocate double[] array
    return N;
}



Для меня что-то совсем не понятное. Пишут, что через gcnew выделенная память управляется сборщиком мусора.
Какая сигнатура вызова из C# тоже не ясно.
Может кто знает?
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619744
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsaf, в C++ используй сигнатуру предложенную Изопропил. На стороне C# такую сигнатуру:
Код: c#
1.
2.
3.
4.
[DllImport(...)]
private static extern void MyFunk(
	[Out]out int length,
        [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] out double[] A);
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619753
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут все равно будет копирование в массив А через маршалинг, только не явное. Или я не прав?
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619755
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsaf, да. Этого не избежать если речь идет о взаимодействии с неуправляемым C++ кодом. Ели у тебя есть возможность использовать управляемый вариант C++ (С++/CLI), то по идее использование gcnew для выделения памяти под массив должно избавить от необходимости копировать массив т.к. массив уже находится в управляемой куче. Правда как этим пользоваться я не смогу подсказать.
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619757
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsafТут все равно будет копирование в массив А через маршалинг, только не явное. Или я не прав?

1)c# умеет работать с указателями в C-стиле (так называемый unsafe код)
2) Можно в MyFunc передать параметром свой(c#) аллокатор

чего лучше не делать - франкенштейнв менеджед с++ сюда вовлекать
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619765
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazileЕли у тебя есть возможность использовать управляемый вариант C++ (С++/CLI), то по идее использование gcnew для выделения памяти под массив должно избавить от необходимости копировать массив т.к. массив уже находится в управляемой куче.
Да, возможность есть. Так и буду делать, т.к с++ код сейчас пишет коллега программист. Ему ничего не стоит в опциях компилятора поставить /clr.



Изопропил1)c# умеет работать с указателями в C-стиле (так называемый unsafe код)

И при выходе за пределы fixed с использованием unsafe кода мне все равно придется копировать массив, для того, чтобы его данные можно было использовать при выходе из метода, где он заполняется.



Остановлюсь на С++/CLI. В понедельник будем пробовать.
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619770
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsafИ при выходе за пределы fixed с использованием unsafe кода мне все равно придется копировать массив, для того, чтобы его данные можно было использовать при выходе из метода, где он заполняется.
это не так

vlsafЕму ничего не стоит в опциях компилятора поставить /clr
посмотрим

имхо оптимальный вариант:
Код: plaintext
1.
2.
typedef  double*   ( __stdcall *dallocator)(int sz);
extern  "C" __declspec(dllexport) void __stdcall   MyFunc(dallocator a );


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
	double[] arr;
            GCHandle h = new GCHandle();
            Tst.MyFunc(
                (s)=>{
                    arr = new double[s];
                    h = GCHandle.Alloc(arr, GCHandleType.Pinned);
                    return h.AddrOfPinnedObject(); 
                } );
            h.Free();
//arr - результат
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619777
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
c#
Код: c#
1.
2.
public delegate IntPtr dallocator(int sz);
public static extern int MyFunc(dallocator a );
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619801
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv +1
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38619806
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил, спасибо. Но понять тяжело. С аллокаторами в первый раз встречаюсь. Да и с понятием pinned тоже.

Можешь пояснить на пальцах, как это все работает? И как будет выглядеть вызов на C#?
Вот так не получается:
Код: c#
1.
2.
3.
4.
5.
6.
7.
[DllImport("MyDll", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = false)]
internal static extern int MyFunk(Dallocator a);

public int Dummy(out double[] A)
{
    return MyFunk(A);
}



Выходной параметр A должен быть вначале инициализирован.
Как от Dallocator a перейти к массиву А?
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38620289
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделал-таки :) См тут
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38620305
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsafМожешь пояснить на пальцах, как это все работает?
MyFunk параметром передаётся функция, которая выделяет память
в данном случае функция c# и выделяет память из кучи CLR, запоминает ссылку на массив,
фиксирует массив в памяти(дабы сборщик мусора не переместил неожиданно)
и возвращает указатель в C код

PS CLR - это уже совсем оффтоп
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38620475
vlsaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне нужно было все наоборот. C# должен вызвать функцию на С++. Она в свою очередь выделила бы память массиву и вернула этот массив в С#.
...
Рейтинг: 0 / 0
Создание одномерного массива типа double размерности N
    #38620537
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vlsafМне нужно было все наоборот. C# должен вызвать функцию на С++. Она в свою очередь выделила бы память массиву и вернула этот массив в С#.
почему же наоборот?
c# функция вызывает функцию на с++, а она вызывает callback функцию на c#, которая выделяет память
из кучи c# (CLR), а для заполнения возвращает в функцию с++ обычный указатель
...
Рейтинг: 0 / 0
25 сообщений из 33, страница 1 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / Создание одномерного массива типа double размерности N
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]