C ++ неуправляемая DLL в c # - PullRequest
       14

C ++ неуправляемая DLL в c #

2 голосов
/ 06 сентября 2011

Меня попросили интегрировать веб-камеру ZoneTrigger в мой проект. SDK, представленный на сайте, - это C ++, также образец. Мне удалось получить несколько функций для работы. место, где я застрял, - это функция, в которой char * - это передаваемый параметр. Я много копал и узнал, что MarshalAs нужно использовать ...

функция, из которой я хотел бы импортировать код c ++

//header file
struct ZT_TRIG_STRUCT 
{
int aSize;      //STRUCT size
int CameraIndex;
int SpotIndex;
int SpotType;
char SpotName[32];
DWORD Dummy[16];
};

typedef int (WINAPI *f_ZT_EnumerateHotSpots)(int SpotIndex, char *Name, int *SpotType);
/*
You application can call this functions to retrieve information about spots by iterating the SpotIndex param.
Name is a pointer to a 32 byte buffer supplied by your application.
SpotType is a pointer to an 32 bit integer in your application.
Return value:
0 = Success, the Name and SpotType have been initialized
1 = Error, we have lost communication with Zone Trigger
2 = Enumaration is over, all spots have been enumerated. Your application should increment SpotIndex until this function returns 2.
*/

//code
//Enumerate current spots in Zone Trigger
int i=0;
char SpotName[32];
int SpotType;
check = ZT_EnumerateHotSpots(i, SpotName, &SpotType);
while (check == 0) 
{
    float sensitivity = ZT_GetSensitivity(i);
    printf("Zone Trigger spot: %s   Sensitivity: %0.1f%%\r\n", SpotName,     sensitivity*100);
    check = ZT_EnumerateHotSpots(++i, SpotName, &SpotType);
}

Так что при конвертации в c #

[DllImport("ZTcom.dll")]
    private static extern int ZT_EnumerateHotSpots(int i, [MarshalAs(UnmanagedType.LPWStr)]ref string SpotName, ref int SpotType);

 public unsafe struct ZT_TRIG_STRUCT 
    {
        public int aSize;       //STRUCT size
        public int CameraIndex;
        public int SpotIndex;
        public int SpotType;
      public string SpotName ;  
        //[MarshalAs(UnmanagedType.LPStr, SizeConst = 256)] string SpotName;
       // public IntPtr SpotName;
    }

//In code
int i = 0;
 string SpotName;
int SpotType;
check = ZT_EnumerateHotSpots(i, ref SpotName, ref SpotType);

приведенная выше строка дает:

Exception of type 'System.ExecutionEngineException' was thrown.

ОШИБКА.

я знаю, что проблема в SpotName, это байт [32], если я не использую marshalAs, вместо этого я использую только char, это работает n дает первый символ код, где он работает нормально, дает первый символ ниже

 public unsafe struct ZT_TRIG_STRUCT 
    {
        public int aSize;       //STRUCT size
        public int CameraIndex;
        public int SpotIndex;
        public int SpotType;
      public char SpotName ;              
    }

 [DllImport("ZTcom.dll")]
    private static extern int ZT_EnumerateHotSpots(int i, ref char SpotName, ref int SpotType);

 public char SpotName;
int i = 0;
            check = ZT_EnumerateHotSpots(i, ref SpotName, ref SpotType);
            while (check == 0)
            {
                float sensitivity = ZT_GetSensitivity(i);
                textBox1.Text = textBox1.Text + "\r\n" +"Zone Trigger spot: " + SpotName + "   Sensitivity: " + (sensitivity * 100).ToString();
                check = ZT_EnumerateHotSpots(++i, ref SpotName, ref SpotType);
            }

но если я положу char [], это даст

Method's type signature is not Interop compatible. ERROR

У меня закончились варианты ... где я ошибся? я должен использовать MarshalAs или char [] ??? пожалуйста помоги..... Заранее спасибо ....

1 Ответ

4 голосов
/ 06 сентября 2011

Я не вижу, где вы используете ZT_TRIG_STRUCT, но это должно быть объявлено следующим образом:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ZT_TRIG_STRUCT 
{
    public int aSize;
    public int CameraIndex;
    public int SpotIndex;
    public int SpotType;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public string SpotName;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=16)]
    public uint[] Dummy;
}

Другая проблема, с которой вы столкнулись, заключается в объявлении ZT_EnumerateHotSpots.Это должно быть:

[DllImport("ZTcom.dll", CharSet=CharSet.Ansi)]
private static extern int ZT_EnumerateHotSpots(
    int SpotIndex, 
    StringBuilder SpotName, 
    out int SpotType
);

Когда я читаю его, SpotName на самом деле является выходным параметром, т.е. вы предоставляете буфер и ZT_EnumerateHotSpots записывает в него.

Затем вы вызываетевот так

int SpotIndex = 0;
StringBuilder SpotName = new StringBuilder(32);
int SpotType;
int result = ZT_EnumerateHotSpots(SpotIndex, SpotName, out SpotType);
...