Не могу вызвать функцию из dll в C#

356
31 мая 2017, 02:28

Пытаюсь вызвать функцию rgethstpar_date из библиотеки Honeywell hscnetapi.dll в C# 4 VS 2010.

int rgethstpar_date
(
char* server,
int num_gethsts,
rgethstpar_date_data* gethstpar_date_data
);

Параметры:

server (in) Name of the server that the database resides on

num_gethsts (in) The number of points passed to rgethstpar_xxxx in the gethstpar_xxxx_data argument

gethstpar_xxxx_data (in/out) Pointer to a series of rgethstpar_xxxx_data structures (one for each point)

Структура:

/* define structure for RGETHST_DATE procedure call */
struct rgethst_date_data_str
{
    n_ushort        hist_type;
    n_ulong         hist_start_date;
    n_float         hist_start_time;
    n_ushort        num_hist;
    n_ushort        num_points;
    n_ushort        *point_type_nums;
    n_ushort        *point_params;
    n_char          *archive_path;
    n_float         *hist_values;
    n_ushort        gethst_status;
};

Описание структуры:

uint2 hist_type (in) Defines the type of history to retrieve, this will be one of the standard server history types. Namely using one of the following: HST_1MIN, HST_6MIN, HST_1HOUR, HST_8HOUR, HST_24HOUR, HST_5SECF, HST_1HOURE, HST_8HOURE, HST_24HOURE

uint4 hist_start_date (in) Start date of history to receive in Julian days (number of days since 1st January 1981).

ureal4 hist_start_time (in) Start time of history to retrieve in seconds since midnight.

uint2 num_hist (in) Number of history values per point to be retrieved.

uint2 num_points (in) Number of points to be processed. MAXIMUM value allowed is 20.

uint2* point_type_nums (in) Array (of dimension num_points) containing the point type/numbers of the point history values to retrieve.

uint2* point_params (in) Array of (dimension num_points) containing the parameter numbers of the history values to retrieve.

uchar* archive path (in) Pointer to the NULL-terminated string containing the archive pathname of the archive file. A NULL pointer implies that the system will use current history and any archive files which correspond to the value of the date and time parameters.

real4* hist_values (out) Array (of dimension num_points * num_hist) to provide storage for the returned history values.

uint2 gethst_status (out) Return value of the actual remote gethst_date call.

Написал тестовый код:

[DllImportAttribute("hscnetapi.dll", CharSet = CharSet.Ansi, EntryPoint = "rgethstpar_date", CallingConvention = CallingConvention.StdCall)]
public static extern int rgethstpar_date([MarshalAs(UnmanagedType.LPStr)] String server, int num_gethsts, [In, Out] GetArchData[] gethstpar_date_data);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct GetArchData
{
public UInt16 hist_type;            
public UInt32 hist_start_date;
public float hist_start_time;
public UInt16 num_hist;
public UInt16 num_points;          
[MarshalAs(UnmanagedType.LPArray)]
public UInt16[] point_type_nums;
[MarshalAs(UnmanagedType.LPArray)]
public UInt16[] point_params;
[MarshalAs(UnmanagedType.LPStr)]
public String archive_path;
[MarshalAs(UnmanagedType.LPArray)]
public float[] hist_values;
public UInt16 gethst_status;
public GetArchData(UInt16 hist_type, UInt32 hist_start_date, float hist_start_time, UInt16 num_hist, UInt16 num_points, UInt16[] point_type_nums, UInt16[] point_params, String archive_path, float[] hist_values, UInt16 gethst_status)
{
this.hist_type = hist_type;
this.hist_start_date = hist_start_date;
this.hist_start_time = hist_start_time;
this.num_hist = num_hist;
this.num_points = num_points;
this.point_type_nums = point_type_nums;
this.point_params = point_params;
this.archive_path = archive_path;
this.hist_values = hist_values;
this.gethst_status = gethst_status;
}
}
string server = "SRV1";
UInt16 hist_type = 3;
DateTime start_date = new DateTime(2017, 05, 29, 04, 00, 00);
UInt32 hist_start_date = (UInt32)start_date.Subtract(new DateTime(1981, 1, 1, 0, 0, 0, DateTimeKind.Local)).Days;
float hist_start_time = (float)(start_date.Hour * 60 + start_date.Minute * 60 + start_date.Second);
UInt16[] point_type_nums = new UInt16[20];
point_params[0] = 5582;
UInt16[] point_params = new UInt16[20];
point_params[0] = 1;
String archive_path = null;
float[] hist_values = new float[20];
UInt16 gethst_status = 0;                       
GetArchData[] gethstpar_date_data = { new GetArchData(hist_type, hist_start_date, hist_start_time, 1, 20, point_type_nums, point_params, archive_path, hist_values, gethst_status) };
status = NativeMethods.rgethstpar_date(server, 1, gethstpar_date_data);

Весь код на pastebin

Программа завершается с ошибкой:

Unhandled Exception: System.TypeLoadException: Cannot marshal field 'point_type_
nums' of type 'GetArchData': Invalid managed/unmanaged type combination (Array f
ields must be paired with ByValArray or SafeArray).
   at System.StubHelpers.MngdNativeArrayMarshaler.ConvertContentsToNative(IntPtr
 pMarshalState, Object& pManagedHome, IntPtr pNativeHome)
   at netapi_con.Program.NativeMethods.rgethstpar_date(String server, Int32 num_
gethsts, GetArchData[] gethstpar_date_data)
   at netapi_con.Program.Main(String[] args) in C:\Users\ExperionAdmin\Documents
\Visual Studio 2010\Projects\netapi_con\netapi_con\Program.cs:line 136

Как правильно передать такую структуру в функцию rgethstpar_date из dll?

READ ALSO
Конвертер DateTime из dataGridView в MsSql

Конвертер DateTime из dataGridView в MsSql

Доброе утро, у меня из бд отображается datagridView, проблема в том что последний столбец является типом datetime и обратно из грида в бд он не парсится...

254
Видео плеер своими руками на C#

Видео плеер своими руками на C#

Всем приветХочу попробовать сделать видео плеер, который будет читать следующие форматы: AVI, WMV, MOV, MKV, 3gp и т

475
Как загрузить вторую форму в фоновом режиме?

Как загрузить вторую форму в фоновом режиме?

Как при открытии приложения, загрузить форму Form2 в фоновом режиме, при условии, что сначала загружается FormMain (основная форма, при открытии...

217
Убрать выделение первой ячейки в DataGridView

Убрать выделение первой ячейки в DataGridView

Здравствуйте, нашёл вот такой код для запрета в DataGridView использования символов кроме цифр и запятых

356