Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 24.11.2017
Сообщений: 6
1

Тонкости использование нативных dll в C#

24.11.2017, 09:41. Показов 1508. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день. Сразу прошу прошения C# я занимаюсь всего 2 месяца.

Имею нативную DLL на Си для общения с 3D джойстиком.

Прототипы функции реализованные на Си

1. Функции чтения параметров.
C++
1
2
HDAPI void HDAPIENTRY hdGetDoublev(HDenum pname, HDdouble *params);
HDAPI void HDAPIENTRY hdGetLongv(HDenum pname, HDlong *params);
Функция чтения параметра hdGetLongv может читать один или несколько элементов типа long.

Чтение параметров реализована через синхронную функцию "шедулера"
2. Прототип фунции
C++
1
HDAPI void HDAPIENTRY hdScheduleSynchronous(HDSchedulerCallback pCallback, void *pUserData, HDushort nPriority);
В качестве параметра функции "шедулера" передается Callback функция в теле которой происходит чтение параметров
3. Реализация функции Callback

C++
1
2
3
4
5
6
7
    HDCallbackCode HDCALLBACK Touch3D_GetCurrentEncoder_Callback(void *pUserData)
    {
        hdBeginFrame(hdGetCurrentDevice());
        hdGetLongv(HD_CURRENT_ENCODER_VALUES, (HDlong *)pUserData);
        hdEndFrame(hdGetCurrentDevice());
        return HD_CALLBACK_DONE;
    }
Вызов происходит следующей функцией.

C++
1
2
3
4
    void Touch3D_GetCurrentEncoder(TEncoderData *data)
    {
        hdScheduleSynchronous(Touch3D_GetCurrentEncoder_Callback, data, HD_DEFAULT_SCHEDULER_PRIORITY);
    }
где
C++
1
2
3
4
5
6
7
8
9
10
typedef struct
    {
        public: long x;
        public: long y;
        public: long z;
        public: long gimbal_x;
        public: long gimbal_y;
        public: long gimbal_z;
    }
    TEncoderData;
На выходе я получаю заполненную структуру.

Я реализовал следующий вариант использования на C#

Прототипы функций из DLL

C#
1
2
3
4
5
6
7
8
 [DllImport("hd.dll")]
 private static extern void hdGetLongv(uint pname, ref long pParams);
 
 [DllImport("hd.dll")]
 private static extern void hdScheduleSynchronous(HDSchedulerCallback pCallback, ref object pUserData, ushort nPriority);
 
Для функции Callback я объявил 
public delegate uint HDSchedulerCallback(ref object pUserData); // как бы typedef

Реализация Callback

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
     uint Touch3D_GetCurrentEncoder_Callback(ref object pUserData)
        {
            long[] temp = (long[])pUserData;
            hdBeginFrame(hdGetCurrentDevice());
            hdGetLongv(HD_CURRENT_ENCODER_VALUES, ref temp[0]);
            hdEndFrame(hdGetCurrentDevice());
            return HD_CALLBACK_DONE;
        }
 
        void Touch3D_GetCurrentEncoder(ref long[] Data)
        {
             object data= Data;
             hdScheduleSynchronous(Touch3D_GetCurrentEncoder_Callback, ref data, (ushort)HD_DEFAULT_SCHEDULER_PRIORITY);
         }
Использую

C#
1
2
3
4
int[] arr = new int[6];
  arr = 0;
           
  Touch3D_GetCurrentEncoder(ref arr);

Эта функция вызывается каждые 100 мс. И мне не нравится вариант что постоянно создаются новые объекты:
object data= Data;
long[] temp = (long[])pUserData;


Подскажите правильный метод решения задачи. Исходников Dll у меня нет
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.11.2017, 09:41
Ответы с готовыми решениями:

Использование нативных библиотек
Добрый день. Решил попробовать написать приложение для личных нужд, нашел хорошее описание и уперся...

Путь изучения С++ для написания нативных dll библиотек?
Здравствуйте. Возможно, что вопрос очень простой и много уже где задавался. Суть вопроса такова....

Использование String Tables в .dll(.dll.mui) (Для VB .NET)
Здравствуйте. Нужно извлечь(а потом запоковать) таблицу строк(string tables ). Допустим есть...

Использование функций DLL из другой DLL
Ребята подскажите имеется hscli.DLL hscli.LIB и hscli.H , собираю свою DLL-ку , которая...

10
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,605
24.11.2017, 10:17 2
sprutkmv, а где тут объекты создаются? Кроме int[] arr = new int[6]; я ничего такого не вижу. Вы может создать ОДИН экземпляр массива и переиспользовать его.
0
0 / 0 / 0
Регистрация: 24.11.2017
Сообщений: 6
24.11.2017, 10:24  [ТС] 3
а разве в таком варианте он не создает объект long[] temp = (long[])pUserData;

В принципе память не течет, так что наверно остановлюсь на таком варианте.
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,605
24.11.2017, 10:35 4
sprutkmv, это называется "приведение типа". Существующий тип начинает трактоваться как другой. Нигде ничего не создаётся.
1
0 / 0 / 0
Регистрация: 24.11.2017
Сообщений: 6
24.11.2017, 10:45  [ТС] 5
Теперь понял. Подскажите как грамотно привести структуру
C++
1
2
3
4
5
6
7
8
9
10
    typedef struct
    {
        public: long x;
        public: long y;
        public: long z;
        public: long gimbal_x;
        public: long gimbal_y;
        public: long gimbal_z;
    }
    TEncoderData;
К массиву
C#
1
long[] temp
и обратно
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,605
24.11.2017, 11:03 6
sprutkmv, что?

Добавлено через 54 секунды
Вам из полей структуры нужно массив получить?
0
0 / 0 / 0
Регистрация: 24.11.2017
Сообщений: 6
24.11.2017, 11:11  [ТС] 7
мне удобнее использовать функцию
C#
1
Touch3D_GetCurrentEncoder(TEncoderData);
к сожалению функция
C++
1
HDAPI void HDAPIENTRY hdGetLongv(HDenum pname, HDlong *params);
возвращает значение через указатель
C++
1
HDlong *params
В Си я просто передаю структуру TEncoderData как указатель с приведением типа
C++
1
(HDlong *)TEncoderData
Как сделать аналогично в C# я не знаю.

В C# что бы функция hdGetLongv передала несколько значений я ей передаю первый элемент массива ref temp[0].
Теперь мне нужно long[] temp привести к TEncoderData
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,605
24.11.2017, 11:35 8
sprutkmv, в C# вам тоже нужно работать со структурой. И передавать указатель на неё, а не ссылку на первый элемент массива.
0
0 / 0 / 0
Регистрация: 24.11.2017
Сообщений: 6
24.11.2017, 11:40  [ТС] 9
А как это сделать.
Разве C# не размещает поля структуры по своему усмотрению
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,605
24.11.2017, 11:45 10
sprutkmv, размещает. Но ему можно дать указание как размещать поля в структуре. Посмотрите, пожалуйста, данный замечательный FAQ. Там много по вашей теме.
1
0 / 0 / 0
Регистрация: 24.11.2017
Сообщений: 6
24.11.2017, 11:54  [ТС] 11
Я правильно понимаю, что мой вопрос можно решить только используя так называемый "не безопасный код"?
Спасибо буду изучать
0
24.11.2017, 11:54
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.11.2017, 11:54
Помогаю со студенческими работами здесь

Загрузка нативных библиотек
Доброго времени суток! Пытался загрузить .dll библиотеку, но почему-то это не получается. Кидает...

Использование DLL
Ребят, привет! Решил побаловаться и научиться создавать библиотеки DLL/LIB. С либом - все в...

Использование Dll
Извините за нубский вопрос. Мне чтобы определиться, распланировать дальнейшие действия нужно знать,...

Использование dll в c++
Подскажите пожалуйста, как правильно создать и использовать dll библиотеку в c++? Делаю так....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru