C-функция в VB.NET - PullRequest
       17

C-функция в VB.NET

0 голосов
/ 07 декабря 2009

У меня возникли проблемы с вызовом функции C из DLL, и я надеялся, что кто-нибудь мне поможет. Функция возвращает -101, что переводится как «неверный параметр». Значения, которые я передаю, были возвращены из другого успешного вызова функции, поэтому мое текущее предположение состоит в том, что я построил структуру неправильно Любая помощь приветствуется.

Определение функции:

int sm_switch_channel_input(struct sm_switch_channel_parms *switchp) 

Parameters
*switchp (a structure of the following type): 
typedef struct sm_switch_channel_parms {
     tSMChannelId channel;     /* in */
     tSM_INT st;      /* in */
     tSM_INT ts;      /* in */
     enum kSMTimeslotType type;    /* in */
} SM_SWITCH_CHANNEL_PARMS;

typedef struct tSMChannelId_struct *tSMChannelId;
typedef int tSM_INT;
enum kSMTimeslotType {
 kSMTimeslotTypeALaw,
 kSMTimeslotTypeMuLaw,
 kSMTimeslotTypeData,
};

А вот как я это определил и назвал ...

Enum kSMTimeslotType
    kSMTimeslotTypeALaw = 0
    kSMTimeslotTypeMuLaw = 1
    kSMTimeslotTypeData = 2
End Enum
Public Structure sm_switch_channel_input_params
    <MarshalAsAttribute(UnmanagedType.SysInt)> _
    Public channel As IntPtr
    <MarshalAsAttribute(UnmanagedType.I4)> _
    Public stream As Integer
    <MarshalAsAttribute(UnmanagedType.I4)> _
    Public timeslot As Integer
    <MarshalAsAttribute(UnmanagedType.U4)> _
    Public tsType As kSMTimeslotType
End Structure

<DllImport("TiNG.dll")> _
Private Shared Function sm_switch_channel_input_iPsCtiie1_3__(ByRef x As sm_switch_channel_input_params) As Integer
End Function

Dim sscip As sm_switch_channel_input_params
Dim err as Integer

sscip.channel = chanA
sscip.stream = streamA
sscip.timeslot = timeSlotA
sscip.tsType = kSMTimeslotType.kSMTimeslotTypeMuLaw
err = sm_switch_channel_input_iPsCtiie1_3__(sscip)

Ответы [ 2 ]

0 голосов
/ 07 декабря 2009

Судя по названию функции в вашем VB-коде, это функция C ++ и экспортируется как таковая. Следовательно, он не использует соглашение о вызовах "stdcall" (которое P / Invoke предполагает по умолчанию), а "thiscall" (которое VC ++ использует для всех не vararg функций C ++). Итак, попробуйте это:

<DllImport("TiNG.dll", CallingConvention := CallingConvention.ThisCall)> _
Private Shared Function sm_switch_channel_input_iPsCtiie1_3__ ...

Более подходящий способ исправить это - украсить функцию в коде C вместо extern "C" и __stdcall:

extern "C" {
    int __stdcall sm_switch_channel_input(struct sm_switch_channel_parms *switchp) 
    ...
}

Тогда ваше оригинальное объявление P / Invoke должно работать как есть.

В качестве примечания, все ваши атрибуты MarshalAs являются избыточными (они задают поведение, которое уже является типом по умолчанию для типов, к которым вы его применяете), поэтому вы можете полностью их удалить.

0 голосов
/ 07 декабря 2009

Я думаю, что атрибут SysInt является причиной вашей проблемы. В этом случае нет необходимости, потому что IntPtr всегда будет правильно распределяться в зависимости от текущей платформы Вам также не хватает атрибута StructLayout

Есть пара других атрибутов, которые также не нужны. Я бы попробовал использовать следующее определение

Enum kSMTimeslotType
    kSMTimeslotTypeALaw = 0
    kSMTimeslotTypeMuLaw = 1
    kSMTimeslotTypeData = 2
End Enum

<StructLayout(LayoutKind.Sequential)> _
Public Structure sm_switch_channel_input_params
    Public channel As IntPtr
    Public stream As Integer
    Public timeslot As Integer
    Public tsType As kSMTimeslotType
End Structure
...