Неуправляемая DLL в C # не работает должным образом - PullRequest
2 голосов
/ 19 июня 2011

Я работал над DLL, которая использует OpenCV для отслеживания. Получил все, что работает над консольным проектом C с использованием VS 2008 (для целей тестирования). Затем я сделал новый проект DLL и скомпилировал его. Я настроил все, поэтому я просто поместил одну функцию в класс Thread для вызова одной функции.

Затем я создал C # проект для GUI и других вещей. DLL загружается нормально (с использованием System.Runtime.InteropServices, метод запускается (я вижу окно захвата, созданное OpenCV), но отслеживание не выполняется. Чтобы убедиться, что DLL действительно работает, я загрузил на Python и вызвал метод и его работает нормально (отслеживание выполняется).

Я новичок в работе с неуправляемыми DLL в управляемом коде. Любые идеи о том, что я делаю не так или как я могу отладить это? Если вам понадобится что-нибудь еще, чтобы помочь мне решить эту проблему, я предоставлю это.

Заранее спасибо.

Edit:

Я не использую класс в DLL, я использую одну функцию, класс Thread происходит от System.Threading на C #

То, как я использую DLL, выглядит следующим образом.

namespace GUI
{
    static class NativeTracking
    {
        [DllImport(@"__Tracking.dll")]
        public static extern void _Tracking();
    }
}

Я положил его на нить, как его

public GUI()
{
    InitializeComponent();
    _tracking = new Thread(_Tracking);
    _tracking.Start();
}

public _Tracking()
{
    while(True)
    {
        NativeTracking.Tracking();
    }
}

Редактировать: родной код

Собственный код, извините за грязный формат.

Заголовочный файл

#include <cv.h>
#include <stdio.h>
#include <ctype.h>
#include <windows.h>
#include <highgui.h>
#include "..\original\project\myheader.h"
#include "..\original\project\myheader1.h"
#include "..\original\project\myheader2.h"
#include "..\original\project\myheader3.h"
#include "..\original\project\myheader4.h"
#ifdef __cplusplus
extern "C"{
#endif

    _declspec(dllexport) void Tracking();

#ifdef __cplusplus
}
#endif

Осуществление

#include "exposed.h"

void Tracking( )
{
int flag = 1, i=0;
iplImgs imgs;
trackingTool tools;
helperTools helperTools;

CvCapture* capture = 0;
capture = cvCaptureFromCAM( 0 );

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240);
cvSetCaptureProperty(capture, CV_CAP_PROP_FPS, 20.0f);

imgs.image = 0;

    cvNamedWindow( "Window", 0 );
initHelperTools(&helperTools);
initTools(&imgs, &tools);

    for(;;){

    int c;
            IplImage* frame = 0;

    frame = cvQueryFrame( capture );        
    if( !frame )
        break;

    if( !imgs.image ){
            /* allocate all the buffers */
            prepareImages(&imgs, &tools, frame);
        }

        cvCopy( frame, imgs.image, 0 );
        cvCvtColor( imgs.image, imgs.grey, CV_BGR2GRAY );

        if( flag == 1 || conditionB ){
        someOperations(&imgs, &tools);
        if (conditionC)
            flag = 0;
        }
    else if( conditionD ){
        otherOps(&helperTools, imgs.grey);
        someTrack(&imgs, &tools, &helperTools, drawPoints);
        someCorrections(&tools);
        if ( condition ){
            if (!wasReset){
                wasReset = 0;
                continue;
            }
            if ( validation )
            someMoreOperations(&tools, corretions);
        }
    }   

    bufferHandlingOps(&imgs);


        c = cvWaitKey(10);
        if( (char)c == 27 )
            break;
    switch ((char)c){
        case 'p':
            drawPoints ^= 1;
            break;
        default:
            ;
    }
    }

    cvReleaseCapture( &capture );
    cvDestroyWindow("Window");
}

Ответы [ 2 ]

3 голосов
/ 19 июня 2011

Одна проблема, которую я вижу, состоит в том, что вы используете соглашение о вызовах C по умолчанию в своем собственном коде, которое является " _ _cdecl " и в вашем P / Invoke "DLLImportmsgstr "атрибут, которому вы позволяете использовать вызов по умолчанию для C #, который" __ stdcall".Это, вероятно, вызывает исключение времени выполнения всякий раз, когда вы вызываете свой собственный метод.

Кроме того, я понимаю, что вы не передаете никаких аргументов или ожидаете каких-либо результатов, но соглашение о вызовах обозначает способ оформления функции, что может привести к искажению имен проблем.Вы можете:

  1. изменить свой собственный экспорт на "__declspec (dllexport) void __stdcall Tracking ();"
  2. или изменить свойство " CallingConvention " на своемАтрибут DLLImport: [DllImport (@ "__ Tracking.dll") CallingConvention = CallingConvention = CallingConvention.Cdecl]
2 голосов
/ 19 июня 2011

Одна из проблем DllImport (P / Invoke) заключается в том, что она не является безопасной.Вы знаете, что он работает только во время выполнения, потому что у вас нет способа проверить его во время компиляции, если:

  • правильная сигнатура метода;
  • искажениеметод правильный.

Он очень популярен для методов WIN32, потому что вы найдете множество примеров, которые работают, но для используемой вами библиотеки это вопрос попытки и попытки, пока она не заработает иливы обнаружите конкретную проблему, которая блокирует вас (не забудьте проверить, что dll находится в том же каталоге или в системном каталоге исполняемого файла при запуске).

Мой совет - создать подходящую оболочку в C ++ /CLI.У него нет проблем, описанных выше, и его сложнее отлаживать в случае проблем. Здесь представляет собой более сложный пример, который я написал в случае обратного вызова в C для раскрытия в C #.

...