Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/13: Рейтинг темы: голосов - 13, средняя оценка - 5.00
3 / 3 / 3
Регистрация: 26.09.2009
Сообщений: 100

DllImport, unsafe код, указатель на функцию

11.06.2017, 00:01. Показов 2803. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Необходимо вызвать функцию из dll, у которой параметром является структура, в которой одно из полей - указатель на функцию. Я не знаю, как средствами C# определить указатель на функцию в unsafe коде. Помогите, пожалуйста, разобраться.
Вот код из заголовочного файла C++
C++
1
2
3
4
5
6
7
8
typedef void (* pF)(void* object);
typedef struct StrA_
{
    void* data;
    pF f1;
} StrA;
 
extern "C" int Func(StrA* s);
C#
1
2
3
4
5
6
7
8
9
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct StrA_
{
    void* data;
    // pF f1; ????
}
 
[DllImport("aaa.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern int Func(StrA_* s);
И нужно ли в данном случае указывать параметр упаковки Pack = 1 или просто [StructLayout(LayoutKind.Sequential)]
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.06.2017, 00:01
Ответы с готовыми решениями:

Как сделать функцию, возвращающую указатель на функцию (которая в свою очередь возвращает указатель на массив)
Изучаю c++ по одной книжке.Она говорить не умеет.. Так вот понадобилось написать функцию,которая как параметр получает указатель на...

В функцию-метод передать указатель на другую функцию-метод и вызвать через переданный указатель
Друзья! Всем привет. Вот код: class otets { public: void f (void (otets::*p)()); private: void echo_f (){}; ...

Unsafe код из с++ на с#
Не уверен в той ли ветке пишу вопрос, но может кто знает.. есть код на ++ необходимо создать аналог на шарпе. Этот код является аналог ...

4
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
11.06.2017, 06:48
Можно использовать IntPtr, и затем получить делегат с помощью Marshal.GetDelegateForFunctionPointer<TDelegate>(IntPtr).
Либо попытаться напрямую использовать делегат с соответствующим MarshalAs аттрибутом.
Сам делегат должен также иметь корректный аттрибут UnmanagedFunctionPointer.

C#
1
2
3
4
5
    [DllImport("aaa.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int Func(ref/*или out*/ StrA_1 s);
 
    [UnmanagedFunctionPointer(CallingConvention.StdCall/*тут нужно указать корректное соглашение вызова...*/)]
    public delegate void pF(IntPtr obj);
C#
1
2
3
4
5
6
7
    [StructLayout(LayoutKind.Sequential)]
    public struct StrA_1
    {
        public IntPtr data;
        [MarshalAs(UnmanagedType.FunctionPtr)]
        public pF f1;
    }
или
C#
1
2
3
4
5
6
7
8
9
10
    [StructLayout(LayoutKind.Sequential)]
    public struct StrA_2
    {
        public IntPtr data;
        public IntPtr f1;
    }
 
    StrA_2 str = new StrA_2();
    // [Supported in the .NET Framework 4.5.1 and later versions]
    pF func = Marshal.GetDelegateForFunctionPointer<pF>(str.f1);
1
3 / 3 / 3
Регистрация: 26.09.2009
Сообщений: 100
12.06.2017, 17:42  [ТС]
Большое спасибо.
Начал копать дальше и возникло ещё несколько неразрешимых для меня проблем (см. (1), (2), (3)). Код на С++ не привожу, думаю будет понятно.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 public static partial class Test
    {
        private const int MAX_MODULES = 32;
 
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate void AllocFunc(long size);
 
        [StructLayout(LayoutKind.Sequential)]
        private struct ModuleRec
        {
            int Val;
            IntPtr data;
        }
 
        [StructLayout(LayoutKind.Sequential)]
        private struct LibraryRec
        {
            IntPtr user;
 
            // (1) если указатель на функцию определить так, то в функции Init() объявление: LibraryRec* library; дает следующую ошибку:
            // "Не удается получить адрес, определить размер или объявить указатель на управляемый тип ("Test.LibraryRec")
            [MarshalAs(UnmanagedType.FunctionPtr)]
            AllocFunc alloc;
 
            // (2) необходимо определить массив указателей на структуру ModuleRec. Как это сделать правильно ?????
            [MarshalAs(UnmanagedType.LPStruct)]
            ModuleRec modules[MAX_MODULES];
        }
 
        [DllImport("freetype6.dll", EntryPoint = "FT_Init_FreeType", CallingConvention = CallingConvention.Cdecl)]
        private unsafe static extern int Init_FreeType(LibraryRec** alibrary);  // (3) можно лиздесь уйти от unsafe кода  ?????
 
        public unsafe static void Init(string FontName, uint hFont)  //(3) можно ли здесь уйти от unsafe кода  ?????
        {
             LibraryRec* library; // здесь ошибка, см. (1). 
            if (Init_FreeType(&library) != 0) throw new InvalidOperationException("Init_FreeType failed");
        }
    }
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
12.06.2017, 17:52
Лучший ответ Сообщение было отмечено Алексей71 как решение

Решение

А почему у вас в Init_FreeType передается LibraryRec**, а не просто LibraryRec*? Быстрое гугление говорит что передается просто указатель...
А если убрать все указатели, добавить ref то все по идее должно заработать...
C#
1
2
[DllImport("freetype6.dll", EntryPoint = "FT_Init_FreeType", CallingConvention = CallingConvention.Cdecl)]
private unsafe static extern int Init_FreeType(out LibraryRec alibrary);
Кстати, есть же готовые библиотеки
https://github.com/Robmaister/SharpFont
https://www.nuget.org/packages/SharpFont/

И вот код по которому вы задали вопрос: https://github.com/Robmaister/... Type&type=
1
3 / 3 / 3
Регистрация: 26.09.2009
Сообщений: 100
12.06.2017, 22:17  [ТС]
В оригинале так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef struct  FT_LibraryRec_
{
       ...
       ...
} FT_LibraryRec;
 
typedef struct FT_LibraryRec_  *FT_Library;
void font_data::init(const char * fname, unsigned int h) {
        ...
 
    //Create and initilize a freetype font library.
    FT_Library library;
    if (FT_Init_FreeType( &library )) 
        throw std::runtime_error("FT_Init_FreeType failed");
 
          ...
}
Я вообще хочу сглаженные шрифты в C# в OpenGL

Добавлено через 13 минут
Ок, спасибо, попробую покурить:
https://github.com/Robmaister/SharpFont

Добавлено через 4 часа 2 минуты
Да, то, что надо, странно, что сразу не нагуглил. Ещё раз спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
12.06.2017, 22:17
Помогаю со студенческими работами здесь

Unsafe code requires the `unsafe' command line option to be specified
Как сказать ему что можно использовать unsafe код? (пишу в repl.it)

BitmapData и unsafe-код
Подскажите пожалуйста, как мне с помощью указателей добраться до отдельного пикселя в изображении и получить уже с этого пикселя значения...

небезопасный код (unsafe)
Столкнулся с проблемой: Visual Studio 2010 ругается на unsafe, а именно: &quot;ошибка CS0227: Небезопасный код может использоваться только при...

Есть разница при DLLImport портируем мы процедуру или функцию
Пытаюсь сделать импорт из DLL Delphi. Все работает, но выводит значение nan. и тут случайно заметила что портирую процедуру, а они же не...

Переделать unsafe код в safe
Есть реализация криптоалгоритма Xtea с использованием unsafe кода. Как передалать его в safe? Фрагмент, который нужно переделать. ...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru