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

Вызов функций, возвращающих указатель на структуру, из нативной dll

09.11.2016, 08:53. Показов 5209. Ответов 33
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Тут на форуме уже не раз задавали вопросы, как вызвать функцию из нативной dll. И в случае, если функция возвращает "нормальный" тип, у меня с этим вопросов нет: DllImport и всё такое. Но вот если функция возвращает указатель на интерфейс, вот тут у меня возникли проблемы.
Имеется dll-ка (написана, кажется, на CBuilder), экспортирующая всего 2 функции. Так же имеются примеры работы с этой dll-кой в Delphi и в С++.

На Delphi это выглядит так:

Rtusbapi.pas

Delphi
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
unit Rtusbapi;
 
interface
 
uses
    windows;
 
type
pSHORT = ^SHORT;
pBYTE = ^BYTE;
 
type
 
// структура, задающая режимы ввода данных для модуля USB-3000
INPUT_PARS_USB3000 = packed record   // (size=438)
    size : WORD;
    InputEnabled : BOOL;                                    // флажок разрешение/запрещение ввода данных (только при чтении)
    CorrectionEnabled : BOOL;                           // управление корректировкой входных данных (с АЦП)
    InputClockSource : WORD;                            // источник тактовых импульсов для ввода данных
    InputType : WORD;                                       // тип вводимых с модуля даных (АЦП или ТТЛ)
    SynchroType : WORD;                                 // тип синхронизации вводимых с модуля даных
    SynchroAdType : WORD;                               // тип аналоговой синхронизации
    SynchroAdMode : WORD;                               // режим аналоговой сихронизации
    SynchroAdChannel : WORD;                            // канал АЦП при аналоговой синхронизации
    SynchroAdPorog : SHORT;                             // порог срабатывания АЦП при аналоговой синхронизации
    ChannelsQuantity : WORD;                            // число активных логических каналов
    ControlTable : array [0..127] of WORD;          // управляющая таблица с активными логическими каналами
    InputFifoBaseAddress : WORD;                        // базовый адрес FIFO буфера ввода
    InputFifoLength : WORD;                             // длина FIFO буфера ввода
    InputRate : double;                                 // тактовая частота ввода данных в кГц
    InterKadrDelay : double;                            // межкадровая задержка в мс
    ChannelRate : double;                               // частота ввода фиксированного логического канала
    AdcOffsetCoef : array [0..7] of double;         // корректировочные коэф. смещение нуля для АЦП
    AdcScaleCoef : array [0..7] of double;          // корректировочные коэф. масштаба для АЦП
end;
pINPUT_PARS_USB3000 = ^INPUT_PARS_USB3000;
 
// структура, задающая режимы вывода данных для модуля USB-3000
OUTPUT_PARS_USB3000 = packed record    // (size = 18)
    size : WORD;
    OutputEnabled : BOOL;                               // разрешение/запрещение вывода данных
    OutputRate : double;                                    // частота вывода данных в кГц
    OutputFifoBaseAddress : WORD;                   // базовый адрес FIFO буфера вывода
    OutputFifoLength : WORD;                            // длина FIFO буфера вывода
end;
pOUTPUT_PARS_USB3000 = ^OUTPUT_PARS_USB3000;
 
// структура пользовательского ППЗУ
FLASH_USB3000 = packed record           // (size = 256)
    CRC16 : WORD;                                           // контрольная сумма
    size : WORD;                                            // размер структуры
    SerialNumber : array [0..8] of BYTE;            // серийный номер модуля
    Name : array [0..10] of BYTE;                       // название модуля
    Revision : CHAR;                                        // ревизия модуля
    DspType : array [0..16] of BYTE;                    // тип установленного DSP
    IsDacPresented : BYTE;                              // флажок наличия ЦАП
    DspClockout : DWORD;                                // тактовая частота DSP в Гц
    AdcOffsetCoef : array [0..7] of single;         // корректировочные коэф. смещения нуля для АЦП
    AdcScaleCoef : array [0..7] of single;          // корректировочные коэф. масштаба для АЦП
    DacOffsetCoef : array [0..1] of single;         // корректировочные коэф. смещения нуля для ЦАП
    DacScaleCoef : array [0..1] of single;          // корректировочные коэф. масштаба для ЦАП
    ReservedByte : array [0..128] of BYTE;          // зарезервировано
end;
pFLASH_USB3000 = ^FLASH_USB3000;
 
// структура, содержащая информацию о версии драйвера DSP
DSP_INFO_USB3000 = packed record    // (size = 18)
    Target : array [0..9] of BYTE;                  //  модуль, для которого предназначен данный драйвер DSP
    DrvLabel : array [0..5] of BYTE;                    // метка разработчика драйвера DSP
    DspMajor : BYTE;                                        // старшие число версии драйвера DSP
    DspMinor : BYTE;                                        // младшее число версии драйвера DSP
end;
pDSP_INFO_USB3000 = ^DSP_INFO_USB3000;
 
// интерфейс модуля USB3000                                       `
IRTUSB3000 = class
  public
    // USB интерфейс модуля
    Function OpenDevice(VirtualSlot : WORD) : boolean; virtual; stdcall; abstract;
    Function CloseDevice : boolean; virtual; stdcall; abstract;
    Function GetModuleHandle : THandle; virtual; stdcall; abstract;
    Function GetUsbSpeed(UsbSpeed : pByte) : boolean; virtual; stdcall; abstract;
    Function GetModuleName(ModuleName : pCHAR) : boolean; virtual; stdcall; abstract;
    Function GetModuleSerialNumber(SerialNumber : pCHAR) : boolean; virtual; stdcall; abstract;
    Function GetAvrVersion(AvrVersion : pCHAR) : boolean; virtual; stdcall; abstract;
    Function ReleaseInstance : boolean; virtual; stdcall; abstract;
 
    // функции для работы с DSP модуля
    Function RESET_DSP : boolean; virtual; stdcall; abstract;
    Function LOAD_DSP(FileName : pCHAR = nil) : boolean; virtual; stdcall; abstract;
    Function MODULE_TEST : boolean; virtual; stdcall; abstract;
    Function GET_DSP_INFO(DspInfo : pDSP_INFO_USB3000): boolean; virtual; stdcall; abstract;
    Function SEND_COMMAND(Command : WORD) : boolean; virtual; stdcall; abstract;
 
    // функции для работы с памятью DSP модуля
    Function PUT_VAR_WORD(Address : WORD; Data : SHORT) : boolean; virtual; stdcall; abstract;
    Function GET_VAR_WORD(Address : WORD; Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function PUT_DM_WORD(Address : WORD; Data : SHORT) : boolean; virtual; stdcall; abstract;
    Function GET_DM_WORD(Address : WORD; Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function PUT_PM_WORD(Address : WORD; Data : DWORD) : boolean; virtual; stdcall; abstract;
    Function GET_PM_WORD(Address : WORD; Data : pDWORD) : boolean; virtual; stdcall; abstract;
    Function PUT_DM_ARRAY(BaseAddress, NPoints : WORD; Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function GET_DM_ARRAY(BaseAddress, NPoints : WORD; Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function PUT_PM_ARRAY(BaseAddress, NPoints : WORD; Data : pDWORD) : boolean; virtual; stdcall; abstract;
    Function GET_PM_ARRAY(BaseAddress, NPoints : WORD; Data : pDWORD) : boolean; virtual; stdcall; abstract;
 
    // функции для работы в режиме ввода данных
    Function GET_INPUT_PARS(ap : pINPUT_PARS_USB3000) : boolean; virtual; stdcall; abstract;
    Function SET_INPUT_PARS(ap : pINPUT_PARS_USB3000) : boolean; virtual; stdcall; abstract;
    Function START_READ : boolean; virtual; stdcall; abstract;
    Function STOP_READ : boolean; virtual; stdcall; abstract;
    Function READ_KADR(Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function READ_SAMPLE(Channel : WORD; Sample : pSHORT) : boolean; virtual; stdcall; abstract;
    Function ReadData(lpBuffer : pSHORT; nNumberOfWordsToRead, lpNumberOfBytesRead : pDWORD; lpOverlapped : POverlapped) : boolean; virtual; stdcall; abstract;
 
    // функции для работы в режиме вывода данных
    Function GET_OUTPUT_PARS(dp : pOUTPUT_PARS_USB3000) : boolean; virtual; stdcall; abstract;
    Function SET_OUTPUT_PARS(dp : pOUTPUT_PARS_USB3000) : boolean; virtual; stdcall; abstract;
    Function START_WRITE : boolean; virtual; stdcall; abstract;
    Function STOP_WRITE : boolean; virtual; stdcall; abstract;
    Function WRITE_SAMPLE(Channel : WORD; Sample : pSHORT) : boolean; virtual; stdcall; abstract;
    Function WriteData(lpBuffer : pSHORT; nNumberOfWordsToWrite, lpNumberOfBytesWritten : pDWORD; lpOverlapped : POverlapped) : boolean; virtual; stdcall; abstract;
 
    // функции для работы с ТТЛ линиями
    Function ENABLE_TTL_OUT(EnabledTtlOut : boolean) : boolean; virtual; stdcall; abstract;
    Function TTL_OUT(TtlOut : WORD) : boolean; virtual; stdcall; abstract;
    Function TTL_IN(TtlIn : pWORD) : boolean; virtual; stdcall; abstract;
 
    // функции для работы ППЗУ
    Function ENABLE_FLASH_WRITE(EnableFlashWrite : boolean) : boolean; virtual; stdcall; abstract;
    Function PUT_FLASH(fi : pFLASH_USB3000) : boolean; virtual; stdcall; abstract;
    Function GET_FLASH(fi : pFLASH_USB3000) : boolean; virtual; stdcall; abstract;
 
    // функция выдачи строки с последней ошибкой
    Function GetLastErrorString(lpBuffer : pCHAR; nSize : DWORD) : Integer; virtual; stdcall; abstract;
end;
PIRTUSB3000 = ^IRTUSB3000;
 
const
// текущая версия библиотеки Rtusbapi.dll
    VERMAJOR_RTUSBAPI           =   $0001;
    VERMINOR_RTUSBAPI           =   $0005;
    CURRENT_VERSION_RTUSBAPI    =   ((VERMAJOR_RTUSBAPI shl 16) or VERMINOR_RTUSBAPI);
 
// объявление экспортируемых из Rtusbapi.dll функций
Function RtGetDllVersion : DWORD; stdcall;
Function RtCreateInstance(DeviceName : PChar) : Pointer; stdcall;
 
implementation
    Function RtGetDllVersion : DWORD; External 'Rtusbapi.dll'
    Function RtCreateInstance(DeviceName : PChar) : Pointer; External 'Rtusbapi.dll'
end.
Вызываются эти функции так:
Delphi
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
var
    // версия библиотеки Rtusbapi.dll
    DllVersion : DWORD;
 
    // интерфейс модуля USB3000
    pModule : IRTUSB3000;
begin
    // проверим версию используемой DLL библиотеки
    DllVersion := RtGetDllVersion; // <-- тут всё понятно
    if DllVersion <> CURRENT_VERSION_RTUSBAPI then
        begin
            ErrorString := 'Неверная версия DLL библиотеки Rtusbapi.dll! ' + #10#13 +
                        '           Текущая: ' + IntToStr(DllVersion shr 16) +  '.' + IntToStr(DllVersion and $FFFF) + '.' +
                        ' Требуется: ' + IntToStr(CURRENT_VERSION_RTUSBAPI shr 16) + '.' + IntToStr(CURRENT_VERSION_RTUSBAPI and $FFFF) + '.';
            TerminateApplication(ErrorString);
        end
    else WriteLn(' DLL Version --> OK');
 
    // попробуем получить указатель на интерфейс для модуля USB3000
    pModule := RtCreateInstance(pCHAR('usb3000')); // <-- а тут на Delphi тоже всё выглядит просто
    if pModule = nil then TerminateApplication('Не могу найти интерфейс модуля USB3000!')
    else WriteLn(' Module Interface --> OK');
 
    // попробуем обнаружить модуль USB3000 в первых 127 виртуальных слотах
    for i := 0 to 126 do
    if pModule.OpenDevice(i) then break; 
 
// и т.д.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
09.11.2016, 08:53
Ответы с готовыми решениями:

Использование функций, возвращающих указатель на указатель
Здравствуйте. Есть несколько функций, которые возвращают указатель на указатель. Вот одна из них: long ZGetBufferADC(long...

Как правильно передать и получить указатель из нативной библиотеки?
Есть некий Сишный код (я опускаю __delc и прочее) с C# я абсолютно не знаком struct Block { int s }

Вызов функций из DLL на С++
В программе:using System; using System.Collections.Generic; using System.Linq; using System.Text; using...

33
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
09.11.2016, 08:54  [ТС]
Теперь пытаюсь реализовать всё это на C#

Rtusbapi.cs
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;
using System.Runtime.InteropServices;
 
namespace Rtusbapi
{
    public class USB3000
    {
        const uint VERMAJOR_RTUSBAPI = 0x1; // только одна цифра
        const uint VERMINOR_RTUSBAPI = 0x5;
        public const uint CURRENT_VERSION_RTUSBAPI = ((VERMAJOR_RTUSBAPI << 0x10) | VERMINOR_RTUSBAPI);
 
        [DllImport(@"Rtusbapi.dll")]
        public static extern uint RtGetDllVersion();
 
        [DllImport(@"Rtusbapi.dll")]
        public static extern object RtCreateInstance(string DeviceName); // пока object, но думаю надо IntPtr, подскажите?
    } 
}
USB3000.cs
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using System;
using System.Runtime.InteropServices;
using System.Threading;
 
namespace Rtusbapi
{
    // структура, задающая режимы ввода данных для модуля USB-3000
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public unsafe struct INPUT_PARS_USB3000                 // size = 438 
    {
        public ushort size;
        public bool InputEnabled;                           // флажок разрешение/запрещение ввода данных (только при чтении)
        public bool CorrectionEnabled;                      // управление корректировкой входных данных (с АЦП)
        public ushort InputClockSource;                     // источник тактовых импульсов для ввода данных
        public ushort InputType;                            // тип вводимых с модуля даных (АЦП или ТТЛ)
        public ushort SynchroType;                          // тип синхронизации вводимых с модуля даных
        public ushort SynchroAdType;                        // тип аналоговой синхронизации
        public ushort SynchroAdMode;                        // режим аналоговой сихронизации
        public ushort SynchroAdChannel;                     // канал АЦП при аналоговой синхронизации
        public short SynchroAdPorog;                        // порог срабатывания АЦП при аналоговой синхронизации
        public ushort ChannelsQuantity;                     // число активных логических каналов
        public fixed ushort ControlTabl[128];               // управляющая таблица с активными логическими каналами
        public ushort InputFifoBaseAddress;                 // базовый адрес FIFO буфера ввода
        public ushort InputFifoLength;                      // длина FIFO буфера ввода
        public double InputRate;                            // тактовая частота ввода данных в кГц
        public double InterKadrDelay;                       // межкадровая задержка в мс
        public double ChannelRate;                          // частота ввода фиксированного логического канала
        public fixed double AdcOffsetCoef[8];               // корректировочные коэф. смещение нуля для АЦП
        public fixed double AdcScaleCoef[8];                // корректировочные коэф. масштаба для АЦП
    }
 
    // структура, задающая режимы вывода данных для модуля USB-3000
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct OUTPUT_PARS_USB3000                       // size = 18 
    {
        public ushort size;
        public bool OutputEnabled;                          // разрешение/запрещение вывода данных
        public double OutputRate;                           // частота вывода данных в кГц
        public ushort OutputFifoBaseAddress;                // базовый адрес FIFO буфера вывода
        public ushort OutputFifoLength;                     // длина FIFO буфера вывода
    }
 
    // структура пользовательского ППЗУ
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public unsafe struct FLASH_USB3000                      // size = 256 
    {
        public ushort CRC16;                                // контрольная сумма
        public ushort size;                                 // размер структуры
        public fixed byte SerialNumber[9];                  // серийный номер модуля
        public fixed byte Name[11];                         // название модуля
        public char Revision;                               // ревизия модуля
        public fixed byte DspType[17];                      // тип установленного DSP
        public byte IsDacPresented;                         // флажок наличия ЦАП
        public uint DspClockout;                            // тактовая частота DSP в Гц
        public fixed float AdcOffsetCoef[8];                // корректировочные коэф. смещения нуля для АЦП
        public fixed float AdcScaleCoef[8];                 // корректировочные коэф. масштаба для АЦП
        public fixed float DacOffsetCoef[2];                // корректировочные коэф. смещения нуля для ЦАП
        public fixed float DacScaleCoef[2];                 // корректировочные коэф. масштаба для ЦАП
        public fixed byte ReservedByte[129];                // зарезервировано
    }
 
    // структура, содержащая информацию о версии драйвера DSP
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public unsafe struct DSP_INFO_USB3000                   // size = 18 
    {
        public fixed byte Target[10];                       //  модуль, для которого предназначен данный драйвер DSP
        public fixed byte DrvLabel[6];                      // метка разработчика драйвера DSP
        public byte DspMajor;                               // старшие число версии драйвера DSP
        public byte DspMinor;                               // младшее число версии драйвера DSP
    }
 
    // интерфейс модуля USB3000                 // вот здесь не знаю как правильно                      `
    public abstract class IRTUSB3000
    {
        // USB интерфейс модуля
        public abstract bool OpenDevice(ushort VirtualSlot); 
        public abstract bool CloseDevice(); 
        public abstract long GetModuleHandle();
        public abstract bool GetUsbSpeed(byte UsbSpeed);
        public abstract bool GetModuleName(string ModuleName);
        public abstract bool GetModuleSerialNumber(string SerialNumber);
        public abstract bool GetAvrVersion(string AvrVersion);
        public abstract bool ReleaseInstance();
 
        // функции для работы с DSP модуля
        public abstract bool RESET_DSP();
        public abstract bool LOAD_DSP(string FileName);
        public abstract bool MODULE_TEST();
        public abstract bool GET_DSP_INFO(DSP_INFO_USB3000 DspInfo);
        public abstract bool SEND_COMMAND(ushort Command);
 
        // функции для работы с памятью DSP модуля
        public abstract bool PUT_VAR_WORD(ushort Address, short Data);
        public abstract bool GET_VAR_WORD(ushort Address, short Data);
        public abstract bool PUT_DM_WORD(ushort Address, short Data);
        public abstract bool GET_DM_WORD(ushort Address, short Data);
        public abstract bool PUT_PM_WORD(ushort Address, int Data);
        public abstract bool GET_PM_WORD(ushort Address, int Data);
        public abstract bool PUT_DM_ARRAY(ushort BaseAddress, ushort NPoints, short Data);
        public abstract bool GET_DM_ARRAY(ushort BaseAddress, ushort NPoints, short Data);
        public abstract bool PUT_PM_ARRAY(ushort BaseAddress, ushort NPoints, int Data);
        public abstract bool GET_PM_ARRAY(ushort BaseAddress, ushort NPoints, int Data);
 
        // функции для работы в режиме ввода данных
        public abstract bool GET_INPUT_PARS(INPUT_PARS_USB3000 ap);
        public abstract bool SET_INPUT_PARS(INPUT_PARS_USB3000 ap);
        public abstract bool START_READ();
        public abstract bool STOP_READ();
        public abstract bool READ_KADR(short Data);
        public abstract bool READ_SAMPLE(ushort Channel, short Sample);
        public abstract bool ReadData(short lpBuffer, uint nNumberOfWordsToRead, uint lpNumberOfBytesRead, Overlapped lpOverlapped);
 
        // функции для работы в режиме вывода данных
        public abstract bool GET_OUTPUT_PARS(OUTPUT_PARS_USB3000 dp);
        public abstract bool SET_OUTPUT_PARS(OUTPUT_PARS_USB3000 dp);
        public abstract bool START_WRITE();
        public abstract bool STOP_WRITE();
        public abstract bool WRITE_SAMPLE(ushort Channel, short Sample);
        public abstract bool WriteData(short lpBuffer, uint nNumberOfWordsToWrite, uint lpNumberOfBytesWritten, Overlapped lpOverlapped);
 
        // функции для работы с ТТЛ линиями
        public abstract bool ENABLE_TTL_OUT(bool EnabledTtlOut);
        public abstract bool TTL_OUT(ushort TtlOut);
        public abstract bool TTL_IN(ushort TtlIn);
 
        // функции для работы ППЗУ
        public abstract bool ENABLE_FLASH_WRITE(bool EnableFlashWrite);
        public abstract bool PUT_FLASH(FLASH_USB3000 fi);
        public abstract bool GET_FLASH(FLASH_USB3000 fi);
 
        // функция выдачи строки с последней ошибкой
        public abstract int GetLastErrorString(string lpBuffer, int nSize);
    }
 
}
Вызов делаю здесь:

Program.cs
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rtusbapi;
 
namespace DynLoadCS
{
    class Program
    {
        public static IRTUSB3000 pModule;
 
        static void Main()
        {
            uint DllVersion;
 
            if ((DllVersion = USB3000.RtGetDllVersion()) != USB3000.CURRENT_VERSION_RTUSBAPI)
            {
                Console.WriteLine(" Rtusbapi.dll Version Error!!!\n  Current: {0}.{1}.  Required: {2}.{3}",
                    DllVersion >> 0x10, DllVersion & 0xFFFF,
                    USB3000.CURRENT_VERSION_RTUSBAPI >> 0x10, USB3000.CURRENT_VERSION_RTUSBAPI & 0xFFFF);
            }
            else Console.WriteLine(" Rtusbapi.dll Version: {0}.{1} --> OK", DllVersion >> 0x10, DllVersion & 0xFFFF);
 
 
            pModule = (IRTUSB3000)USB3000.RtCreateInstance(("usb3000" as string)); // вылетает здесь
 
            Console.ReadKey();
        }
    }
}
Компилируется, но в отладчике вылетает, там, где указал
Code
1
2
3
An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in DynLoadCS.exe
 
Additional information: Ограничение PInvoke: варианты возвращаться не могут.
Собственно вопрос. Как мне реализовать то, что было на Delphi? Как вызывать эти функции?
Проект, примеры, dll и врапперы для неё под Delphi и С++ тут https://drive.google.com/open?... jEtNjBucEk
0
h1f
20 / 1 / 0
Регистрация: 08.12.2015
Сообщений: 5
09.11.2016, 15:34
Нет возможности проверить, но попробуй примерно так:
C#
1
2
3
4
5
IntPtr p = Marshal.GetComInterfaceForObject(USB3000.RtCreateInstance(("usb3000" as string)), typeof(IRTUSB3000));
if(p == IntPtr.Zero)
    // Не могу найти интерфейс модуля USB3000!
else
        // Module Interface --> OK
0
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
09.11.2016, 15:54  [ТС]
GetComInterfaceForObject
в длл-ке не COM
но спасибо, попробую

Добавлено через 12 минут
Попробовал.
C#
1
IntPtr p = Marshal.GetComInterfaceForObject(USB3000.RtCreateInstance(("usb3000" as string)), typeof(IRTUSB3000));
Ограничение PInvoke: варианты возвращаться не могут.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
09.11.2016, 17:31
Лучший ответ Сообщение было отмечено Selya как решение

Решение

Тут посмотрите http://stackoverflow.com/quest... n-pointers

Похоже что там получается что-то типа этого
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
    struct IRTUSB3000Test
    {
        public IntPtr vtable;
        // поля...
    }
 
    struct IRTUSB3000TestVTable
    {
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool Method1Delegate(IntPtr self, ushort VirtualSlot);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool Method2Delegate(IntPtr self);
 
        public Method1Delegate OpenDevice;
        public Method2Delegate CloseDevice;
        // ...
    }
 
    IntPtr structPtr = Rtusbapi.RtCreateInstance("usb3000");
 
    IRTUSB3000Test pModule = (IRTUSB3000Test)Marshal.PtrToStructure(structPtr, typeof(IRTUSB3000Test));
 
    IRTUSB3000TestVTable vt = (IRTUSB3000TestVTable)Marshal.PtrToStructure(pModule.vtable, typeof(IRTUSB3000TestVTable));
 
    bool result = vt.OpenDevice(structPtr, 0);
 
    vt.CloseDevice(structPtr);
1
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
10.11.2016, 09:39  [ТС]
Честно говоря, ещё больше запутался
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
10.11.2016, 17:19
Помоему там все предельно понятно, в С++ в начале структуры/класса, содержащих виртуальные функции всегда находится указатель на таблицу виртуальных функций, сама таблица это просто адреса функций. После указателя на таблицу виртуальных функций идут поля структуры/класса если таковые имеются. Вы хоть пробовали то код запустить и посмотреть как он работает?
0
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
11.11.2016, 09:13  [ТС]
Цитата Сообщение от Someone007 Посмотреть сообщение
struct IRTUSB3000Test
* * {
* * * * public IntPtr vtable;
* * * * // поля...
* * }
// поля
вы имеете ввиду поля OpenDevice, CloseDevice и т.д.?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
11.11.2016, 15:31
Цитата Сообщение от Selya Посмотреть сообщение
вы имеете ввиду поля OpenDevice, CloseDevice и т.д.?
Нет, я же выше написал где функции находятся...
0
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
14.11.2016, 09:36  [ТС]
Someone007, огромное спасибо за желание помочь. Вторую неделю бьюсь, но всё равно не очень понятно.
Ну хорошо, давайте попробуем от простого к сложному.

Фрагмент кода из Rtusbapi.h С++
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
    extern "C" LPVOID WINAPI RtCreateInstance(PCHAR const DeviceName);
 
    struct IRTUSB
    {
        virtual BOOL WINAPI OpenDevice(WORD VirtualSlot) = 0;
        virtual BOOL WINAPI CloseDevice(void) = 0;
        virtual HANDLE WINAPI GetModuleHandle(void) = 0;
        virtual BOOL WINAPI GetUsbSpeed(BYTE * const UsbSpeed) = 0;
        virtual BOOL WINAPI GetModuleName(PCHAR const ModuleName) = 0;
        virtual BOOL WINAPI GetModuleSerialNumber(PCHAR const SerialNumber) = 0;
        virtual BOOL WINAPI GetAvrVersion(PCHAR const AvrVersion) = 0;
        virtual BOOL WINAPI ReleaseInstance(void) = 0;
    };
Вызов в ReadData.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
#include "Rtusbapi.h"
 
IRTUSB *pModule;
 
void main(void)
{
    pModule = static_cast<IRTUSB *>(RtCreateInstance("usb3000"));
    if(!pModule) printf(" Module Interface --> Bad\n");
    else pModule->OpenDevice(0);
 
}
Вот как мне это сделать на С#? Чувствую, что всё должно быть просто
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
14.11.2016, 14:33
В 5 посте рабочий код, осталось туда добавить недостающие 6 из 8 функций (GetModuleHandle и т.д.)...
0
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
14.11.2016, 14:43  [ТС]
Тогда меня смущает
C#
1
2
3
4
5
    struct IRTUSB3000Test
    {
        public IntPtr vtable;
        // поля...
    }
Что за поля?

И ещё смотрю ссылку, что в 5м посте, как-то не очень соотносится, с тем что вы предлагаете.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
14.11.2016, 15:38
Цитата Сообщение от Selya Посмотреть сообщение
И ещё смотрю ссылку, что в 5м посте, как-то не очень соотносится, с тем что вы предлагаете.
Потому что там нет виртуальных функций, а у вас они есть.

Цитата Сообщение от Selya Посмотреть сообщение
Что за поля?
Поля вложенной структуры RTUSB3000::DSP_INFO. Вы хоть смотрели как объявлена структура в С++?

C++
1
2
3
4
5
6
7
8
9
10
11
struct IRTUSB3000 : IRTUSBDSP<RTUSB3000::DSP_INFO> { ... }
 
template <class Type> struct IRTUSBDSP { ... }
 
struct DSP_INFO
{
    BYTE Target[10];
    BYTE Label[6];
    BYTE DspMajor;
    BYTE DspMinor;  
};
0
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
16.11.2016, 13:27  [ТС]
В 5м посте код не рабочий.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
16.11.2016, 16:16
Цитата Сообщение от Selya Посмотреть сообщение
В 5м посте код не рабочий.
И что же там не работает?
0
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
16.11.2016, 19:41  [ТС]
C#
1
2
            IntPtr structPtr = Rtusbapi.RtCreateInstance("usb3000");
            IRTUSB3000 pModule = (IRTUSB3000)Marshal.PtrToStructure(structPtr, typeof(IRTUSB3000)); // <-- тут вылетает
InvalidFunctionPointerInDelegate was detected
Недействительный указатель на функцию 0xffffffff был передан в среду выполнения для преобразования в делегат. Передача недействительных указателей на функции для преобразования в делегаты может вызвать ошибки, а также повреждение или потерю данных.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
16.11.2016, 20:05
Эта ошибка невозможна в коде из 5 поста... Вы там что-то изменили...

Добавлено через 5 минут
Судя по ошибке вы добавили делегаты не в ту структуру...
0
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
17.11.2016, 08:54  [ТС]
Да, изменил. Сделал так:
Rtusbapi.cs
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
using System;
using System.Runtime.InteropServices;
using System.Threading;
 
namespace Rtusbapi
{
    abstract class USB3000_Consts
    {
        // адрес начала сегмента блока данных в памяти программ драйвера DSP
        public const ushort VarsBaseAddress_USB3000                 =   0x30;
            // ...
    }
 
    // структура, задающая режимы ввода данных для модуля USB-3000
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct INPUT_PARS_USB3000                        // size = 438 
    {
        public ushort size;
        [MarshalAs(UnmanagedType.Bool)]
        public bool InputEnabled;
        [MarshalAs(UnmanagedType.Bool)]
        public bool CorrectionEnabled;
        public ushort InputClockSource;             // источник тактовых импульсов для ввода данных
        public ushort InputType;                    // тип вводимых с модуля даных (АЦП или ТТЛ)
        public ushort SynchroType;                  // тип синхронизации вводимых с модуля даных
        public ushort SynchroAdType;                // тип аналоговой синхронизации
        public ushort SynchroAdMode;                // режим аналоговой сихронизации
        public ushort SynchroAdChannel;                 // канал АЦП при аналоговой синхронизации
        public short SynchroAdPorog;                    // порог срабатывания АЦП при аналоговой синхронизации
        public ushort ChannelsQuantity;             // число активных логических каналов
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
        public ushort[] ControlTabl;                        // управляющая таблица с активными логическими каналами
        public ushort InputFifoBaseAddress;         // базовый адрес FIFO буфера ввода
        public ushort InputFifoLength;              // длина FIFO буфера ввода
        public double InputRate;                    // тактовая частота ввода данных в кГц
        public double InterKadrDelay;               // межкадровая задержка в мс
        public double ChannelRate;                  // частота ввода фиксированного логического канала
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public double[] AdcOffsetCoef;                      // корректировочные коэф. смещение нуля для АЦП
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public double[] AdcScaleCoef;                    // корректировочные коэф. масштаба для АЦП
    }
 
    // структура, задающая режимы вывода данных для модуля USB-3000
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct OUTPUT_PARS_USB3000                       // size = 18 
    {
        public ushort size;
        [MarshalAs(UnmanagedType.Bool)]
        public bool OutputEnabled;                  // разрешение/запрещение вывода данных
        public double OutputRate;                   // частота вывода данных в кГц
        public ushort OutputFifoBaseAddress;            // базовый адрес FIFO буфера вывода
        public ushort OutputFifoLength;             // длина FIFO буфера вывода
    }
 
    // структура пользовательского ППЗУ
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct FLASH_USB3000                             // size = 256 
    {
        public ushort CRC16;                        // контрольная сумма
        public ushort size;                     // размер структуры
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
        public byte[] SerialNumber;                         // серийный номер модуля
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
        public byte[] Name;                     // название модуля
        public char Revision;                       // ревизия модуля
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
        public byte[] DspType;                          // тип установленного DSP
        public byte IsDacPresented;                     // флажок наличия ЦАП
        public uint DspClockout;                    // тактовая частота DSP в Гц
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public float[] AdcOffsetCoef;                       // корректировочные коэф. смещения нуля для АЦП
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public float[] AdcScaleCoef;                        // корректировочные коэф. масштаба для АЦП
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        public float[] DacOffsetCoef;                       // корректировочные коэф. смещения нуля для ЦАП
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        public float[] DacScaleCoef;                        // корректировочные коэф. масштаба для ЦАП
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 129)]
        public byte[] ReservedByte;                         // зарезервировано
    }
 
    // структура, содержащая информацию о версии драйвера DSP
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct DSP_INFO_USB3000                          // size = 18 
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
        public byte[] Target;                   // модуль, для которого предназначен данный драйвер DSP
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public byte[] DrvLabel;                 // метка разработчика драйвера DSP
        public byte DspMajor;                   // старшие число версии драйвера DSP
        public byte DspMinor;                   // младшее число версии драйвера DSP
    }
 
    struct IRTUSB3000
    {
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool OpenDeviceDelegate(IntPtr self, ushort VirtualSlot);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool CloseDeviceDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate long GetModuleHandleDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GetUsbSpeedDelegate(IntPtr self, byte UsbSpeed);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GetModuleNameDelegate(IntPtr self, string ModuleName);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GetModuleSerialNumberDelegate(IntPtr self, string SerialNumber);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GetAvrVersionDelegate(IntPtr self, string AvrVersion);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool ReleaseInstanceDelegate(IntPtr self);
 
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool RESET_DSPDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool LOAD_DSPDelegate(IntPtr self, string FileName);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool MODULE_TESTDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GET_DSP_INFODelegate(IntPtr self, DSP_INFO_USB3000 DspInfo);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool SEND_COMMANDDelegate(IntPtr self, ushort Command);
 
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool PUT_VAR_WORDDelegate(IntPtr self, ushort Address, short Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GET_VAR_WORDDelegate(IntPtr self, ushort Address, short Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool PUT_DM_WORDDelegate(IntPtr self, ushort Address, short Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GET_DM_WORDDelegate(IntPtr self, ushort Address, short Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool PUT_PM_WORDDelegate(IntPtr self, ushort Address, int Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GET_PM_WORDDelegate(IntPtr self, ushort Address, int Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool PUT_DM_ARRAYDelegate(IntPtr self, ushort BaseAddress, ushort NPoints, short Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GET_DM_ARRAYDelegate(IntPtr self, ushort BaseAddress, ushort NPoints, short Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool PUT_PM_ARRAYDelegate(IntPtr self, ushort BaseAddress, ushort NPoints, int Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GET_PM_ARRAYDelegate(IntPtr self, ushort BaseAddress, ushort NPoints, int Data);
 
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GET_INPUT_PARSDelegate(IntPtr self, INPUT_PARS_USB3000 ap);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool SET_INPUT_PARSDelegate(IntPtr self, INPUT_PARS_USB3000 ap);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool START_READDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool STOP_READDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool READ_KADRDelegate(IntPtr self, short Data);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool READ_SAMPLEDelegate(IntPtr self, ushort Channel, short Sample);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool ReadDataDelegate(IntPtr self, short lpBuffer, uint nNumberOfWordsToRead, uint lpNumberOfBytesRead, Overlapped lpOverlapped);
 
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GET_OUTPUT_PARSDelegate(IntPtr self, OUTPUT_PARS_USB3000 dp);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool SET_OUTPUT_PARSDelegate(IntPtr self, OUTPUT_PARS_USB3000 dp);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool START_WRITEDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool STOP_WRITEDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool WRITE_SAMPLEDelegate(IntPtr self, ushort Channel, short Sample);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool WriteDataDelegate(short lpBuffer, uint nNumberOfWordsToWrite, uint lpNumberOfBytesWritten, Overlapped lpOverlapped);
 
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool ENABLE_TTL_OUTDelegate(IntPtr self, bool EnabledTtlOut);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool TTL_OUTDelegate(IntPtr self, ushort TtlOut);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool TTL_INDelegate(IntPtr self, ushort TtlIn);
 
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool ENABLE_FLASH_WRITEDelegate(IntPtr self, bool EnableFlashWrite);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool PUT_FLASHDelegate(IntPtr self, FLASH_USB3000 fi);
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate bool GET_FLASHDelegate(IntPtr self, FLASH_USB3000 fi);
 
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate int GetLastErrorStringDelegate(IntPtr self, string lpBuffer, int nSize);
        
 
        public OpenDeviceDelegate OpenDevice;
        public CloseDeviceDelegate CloseDevice;
        public GetModuleHandleDelegate GetModuleHandle;
        public GetUsbSpeedDelegate GetUsbSpeed;
        public GetModuleNameDelegate GetModuleName;
        public GetModuleSerialNumberDelegate GetModuleSerialNumber;
        public GetAvrVersionDelegate GetAvrVersion;
        public ReleaseInstanceDelegate ReleaseInstance;
 
        public RESET_DSPDelegate RESET_DSP;
        public LOAD_DSPDelegate LOAD_DSP;
        public MODULE_TESTDelegate MODULE_TEST;
        public GET_DSP_INFODelegate GET_DSP_INFO;
        public SEND_COMMANDDelegate SEND_COMMAND;
 
        public PUT_VAR_WORDDelegate PUT_VAR_WORD;
        public GET_VAR_WORDDelegate GET_VAR_WORD;
        public PUT_DM_WORDDelegate PUT_DM_WORD;
        public GET_DM_WORDDelegate GET_DM_WORD;
        public PUT_PM_WORDDelegate PUT_PM_WORD;
        public GET_PM_WORDDelegate GET_PM_WORD;
        public PUT_DM_ARRAYDelegate PUT_DM_ARRAY;
        public GET_DM_ARRAYDelegate GET_DM_ARRAY;
        public PUT_PM_ARRAYDelegate PUT_PM_ARRAY;
        public GET_PM_ARRAYDelegate GET_PM_ARRAY;
 
        public GET_INPUT_PARSDelegate GET_INPUT_PARS;
        public SET_INPUT_PARSDelegate SET_INPUT_PARS;
        public START_READDelegate START_READ;
        public STOP_READDelegate STOP_READ;
        public READ_KADRDelegate READ_KADR;
        public READ_SAMPLEDelegate READ_SAMPLE;
        public ReadDataDelegate ReadData;
 
        public GET_OUTPUT_PARSDelegate GET_OUTPUT_PARS;
        public SET_OUTPUT_PARSDelegate SET_OUTPUT_PARS;
        public START_WRITEDelegate START_WRITE;
        public STOP_WRITEDelegate STOP_WRITE;
        public WRITE_SAMPLEDelegate WRITE_SAMPLE;
        public WriteDataDelegate WriteData;
 
        public ENABLE_TTL_OUTDelegate ENABLE_TTL_OUT;
        public TTL_OUTDelegate TTL_OUT;
        public TTL_INDelegate TTL_IN;
 
        public ENABLE_FLASH_WRITEDelegate ENABLE_FLASH_WRITE;
        public PUT_FLASHDelegate PUT_FLASH;
        public GET_FLASHDelegate GET_FLASH;
 
        public GetLastErrorStringDelegate GetLastErrorString;
    }
 
    public static class USB3000
    {
        const uint VERMAJOR_RTUSBAPI = 0x1; // только одна цифра
        const uint VERMINOR_RTUSBAPI = 0x5;
        public const uint CURRENT_VERSION_RTUSBAPI = ((VERMAJOR_RTUSBAPI << 0x10) | VERMINOR_RTUSBAPI);
 
        [DllImport(@"Rtusbapi.dll")]
        public static extern uint RtGetDllVersion();
 
        [DllImport(@"Rtusbapi.dll", EntryPoint = "RtCreateInstance", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr RtCreateInstance([MarshalAs(UnmanagedType.LPStr)]string DeviceName);
    } 
}
Program.cs
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System;
using System.Runtime.InteropServices;
using Rtusbapi;
 
namespace DynLoadCS
{
    class Program
    {
        static void Main()
        {
            IntPtr structPtr = USB3000.RtCreateInstance("usb3000");
            IRTUSB3000 pModule = (IRTUSB3000)Marshal.PtrToStructure(structPtr, typeof(IRTUSB3000));
        }
    }
}
Пожалуйста, посмотрите, что не так.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
17.11.2016, 15:50
Полностью отсутствует указатель на таблицу виртуальных функций. Еще раз внимательно изучите 5 пост, там 2 структуры не просто потому что я так захотел.
0
1 / 1 / 0
Регистрация: 04.09.2014
Сообщений: 21
18.11.2016, 09:55  [ТС]
Ок, переделал. Сделал в точности как советовал товарищ Sam Harwell из ссылки в 5м посте, через interface. Чтобы вызывалось вот так:
C#
1
2
            IRTUSB3000 pModule = USB3000.GetRTUSB3000Interface();
            bool b = pModule.OpenDevice(0);
Rtusbapi.cs
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
using System;
using System.Runtime.InteropServices;
using System.Threading;
 
 
namespace Rtusbapi
{
    abstract class USB3000_Consts
    {
        public const ushort VarsBaseAddress_USB3000           =   0x30;
     // ...
    }
 
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct INPUT_PARS_USB3000        // size = 438 
    {
        public ushort size;
        [MarshalAs(UnmanagedType.Bool)]
        public bool InputEnabled;
// и т.д.
    }
 
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct OUTPUT_PARS_USB3000                       // size = 18 
    {
// и т.д.
    }
 
// и т.д.
 
    internal interface IRTUSB3000
    {
        bool OpenDevice(ushort VirtualSlot);
        bool CloseDevice();
        long GetModuleHandle();
        bool GetUsbSpeed(byte UsbSpeed);
        bool GetModuleName(string ModuleName);
        bool GetModuleSerialNumber(string SerialNumber);
        bool GetAvrVersion(string AvrVersion);
        bool ReleaseInstance();
 
        bool RESET_DSP();
        bool LOAD_DSP(string FileName);
        bool MODULE_TEST();
        bool GET_DSP_INFO(DSP_INFO_USB3000 DspInfo);
        bool SEND_COMMAND(ushort Command);
 
        bool PUT_VAR_WORD(ushort Address, short Data);
        bool GET_VAR_WORD(ushort Address, short Data);
        bool PUT_DM_WORD(ushort Address, short Data);
        bool GET_DM_WORD(ushort Address, short Data);
        bool PUT_PM_WORD(ushort Address, int Data);
        bool GET_PM_WORD(ushort Address, int Data);
        bool PUT_DM_ARRAY(ushort BaseAddress, ushort NPoints, short Data);
        bool GET_DM_ARRAY(ushort BaseAddress, ushort NPoints, short Data);
        bool PUT_PM_ARRAY(ushort BaseAddress, ushort NPoints, int Data);
        bool GET_PM_ARRAY(ushort BaseAddress, ushort NPoints, int Data);
 
        bool GET_INPUT_PARS(INPUT_PARS_USB3000 ap);
        bool SET_INPUT_PARS(INPUT_PARS_USB3000 ap);
        bool START_READ();
        bool STOP_READ();
        bool READ_KADR(short Data);
        bool READ_SAMPLE(ushort Channel, short Sample);
        bool ReadData(short lpBuffer, uint nNumberOfWordsToRead, uint lpNumberOfBytesRead, Overlapped lpOverlapped);
 
        bool GET_OUTPUT_PARS(OUTPUT_PARS_USB3000 dp);
        bool SET_OUTPUT_PARS(OUTPUT_PARS_USB3000 dp);
        bool START_WRITE();
        bool STOP_WRITE();
        bool WRITE_SAMPLE(ushort Channel, short Sample);
        bool WriteData(short lpBuffer, uint nNumberOfWordsToWrite, uint lpNumberOfBytesWritten, Overlapped lpOverlapped);
 
        bool ENABLE_TTL_OUT(bool EnabledTtlOut);
        bool TTL_OUT(ushort TtlOut);
        bool TTL_IN(ushort TtlIn);
 
        bool ENABLE_FLASH_WRITE(bool EnableFlashWrite);
        bool PUT_FLASH(FLASH_USB3000 fi);
        bool GET_FLASH(FLASH_USB3000 fi);
 
        int GetLastErrorString(string lpBuffer, int nSize);
    }
 
    internal static class USB3000
    {
        const uint VERMAJOR_RTUSBAPI = 0x1;
        const uint VERMINOR_RTUSBAPI = 0x5;
        public const uint CURRENT_VERSION_RTUSBAPI = ((VERMAJOR_RTUSBAPI << 0x10) | VERMINOR_RTUSBAPI);
 
        [DllImport(@"Rtusbapi.dll")]
        public static extern uint RtGetDllVersion();
 
        public static IRTUSB3000 GetRTUSB3000Interface()
        {
            IntPtr self = RtCreateInstance("usb3000");
            NativeRTUSB3000 nativeRTUSB3000 = (NativeRTUSB3000)Marshal.PtrToStructure(self, typeof(NativeRTUSB3000)); // <-- вылетает тут
            return new NativeRTUSB3000Wrapper(
                self,
                nativeRTUSB3000.OpenDevice,
                nativeRTUSB3000.CloseDevice,
                nativeRTUSB3000.GetModuleHandle,
                nativeRTUSB3000.GetUsbSpeed,
                nativeRTUSB3000.GetModuleName,
                nativeRTUSB3000.GetModuleSerialNumber,
                nativeRTUSB3000.GetAvrVersion,
                nativeRTUSB3000.ReleaseInstance,
// и т.д.
                );
        }
 
        [DllImport(@"Rtusbapi.dll", EntryPoint = "RtCreateInstance", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] // если Cdecl, то вылетает ошибка PInvokeStackImbalance was detected
        public static extern IntPtr RtCreateInstance([MarshalAs(UnmanagedType.LPStr)]string DeviceName);
 
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool OpenDeviceDelegate(IntPtr self, ushort VirtualSlot);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool CloseDeviceDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate long GetModuleHandleDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool GetUsbSpeedDelegate(IntPtr self, byte UsbSpeed);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool GetModuleNameDelegate(IntPtr self, string ModuleName);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool GetModuleSerialNumberDelegate(IntPtr self, string SerialNumber);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool GetAvrVersionDelegate(IntPtr self, string AvrVersion);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool ReleaseInstanceDelegate(IntPtr self);
// и т.д.
 
        private struct NativeRTUSB3000
        {
            public OpenDeviceDelegate OpenDevice;
            public CloseDeviceDelegate CloseDevice;
            public GetModuleHandleDelegate GetModuleHandle;
            public GetUsbSpeedDelegate GetUsbSpeed;
            public GetModuleNameDelegate GetModuleName;
            public GetModuleSerialNumberDelegate GetModuleSerialNumber;
            public GetAvrVersionDelegate GetAvrVersion;
            public ReleaseInstanceDelegate ReleaseInstance;
// и т.д.
        }
 
        private sealed class NativeRTUSB3000Wrapper : IRTUSB3000
        {
            private IntPtr _self;
            private OpenDeviceDelegate _OpenDevice;
            private CloseDeviceDelegate _CloseDevice;
            private GetModuleHandleDelegate _GetModuleHandle;
            private GetUsbSpeedDelegate _GetUsbSpeed;
            private GetModuleNameDelegate _GetModuleName;
            private GetModuleSerialNumberDelegate _GetModuleSerialNumber;
            private GetAvrVersionDelegate _GetAvrVersion;
            private ReleaseInstanceDelegate _ReleaseInstance;
// и т.д.
 
            public NativeRTUSB3000Wrapper(
                IntPtr self,
                OpenDeviceDelegate OpenDevice,
                CloseDeviceDelegate CloseDevice,
                GetModuleHandleDelegate GetModuleHandle,
                GetUsbSpeedDelegate GetUsbSpeed,
                GetModuleNameDelegate GetModuleName,
                GetModuleSerialNumberDelegate GetModuleSerialNumber,
                GetAvrVersionDelegate GetAvrVersion,
                ReleaseInstanceDelegate ReleaseInstance,
// и т.д.
                GetLastErrorStringDelegate GetLastErrorString)
            {
                this._self = self;
                this._OpenDevice = OpenDevice;
                this._CloseDevice = CloseDevice;
                this._GetModuleHandle = GetModuleHandle;
                this._GetUsbSpeed = GetUsbSpeed;
                this._GetModuleName = GetModuleName;
                this._GetModuleSerialNumber = GetModuleSerialNumber;
                this._GetAvrVersion = GetAvrVersion;
                this._ReleaseInstance = ReleaseInstance;
// и т.д.
            }
 
            public bool OpenDevice(ushort VirtualSlot)
            {
                return _OpenDevice(_self, VirtualSlot);
            }
 
            public bool CloseDevice()
            {
                return _CloseDevice(_self);
            }
// и т.д.
        }
    } 
}
Вылетает в стоке 97
InvalidFunctionPointerInDelegate was detected
Недействительный указатель на функцию 0xffffffff был передан в среду выполнения для преобразования в делегат. Передача недействительных указателей на функции для преобразования в делегаты может вызвать ошибки, а также повреждение или потерю данных.
Прикладываю на всякий случай проект.
Вложения
Тип файла: 7z USB3000.7z (999.1 Кб, 9 просмотров)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.11.2016, 09:55
Помогаю со студенческими работами здесь

Использование функций, возвращающих одно значение
помогите решить: Использование функций, возвращающих одно значение. Даны целочисленные массивы D, A. Для каждого массива определить...

Подключение нативной dll к проекту
Создал C# проект консольный. В одном решении с ним создал win32 пустой проект, указал,что проект пустой и его считать dll библиотекой....

Вызов функций из DLL, написанной на CBuilder.
Всем привет! Есть немаленький софт, написанный на CBuilder. Нужно подгрузить в программе на C# готовые бибилиотеки. Нашел, что с...

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

Экспорт функций из dll на c++ и вызов из Delphi
Вызываю экспортируемую функцию из dll которая написана на c++. Вызываю из Delphi, с вызовом проблем нет но когда оно принимает мою строку...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru