На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> Проблемы с подключением библиотеки
    Приветствую!

    Вот уже неделю (а то и больше) не могу разрешить следующую проблему: есть библиотека, написанная в Visual C++ .NET и проэкт, использующий ее, написанный в Visual Basic .NET. Библиотека предназначена для построения стрктуры данных в памяти (дву-связный список) по переданному ей массиву и работы с ним (перестановки и т.п.). Когда я вызываю процедуру построения этого списка, все вроде бы нормально и никаких ошибок не происходит. Но стоит мне вызвать хоть одну функцию работы со списком и вылетает ексепшн: NullReferenceException. Как будто указатель на начало списка укаывает в нуль, но из приведенного мной кода (см. ниже), явно видно, что такого быть не может. Тем более, когда я проверял все функции этой библиотеки в программе (без вызова их из DLL, они были описаны в той же программе) они работали и не происходило ошиок. Или я совсем ничего не понимаю, или все таки у DLL свой сегмент данных, и в нем должно все сохраняться. Вот код библиотеки (не весь, я указал лишь одну функцию работы со списком - Perform2OPT):

    Цитата

    #include <windows.h>

    typedef struct City {
         unsigned int Data;
         struct City *Next, *Prev;
    } TCity;

    // common functions
    void SetDistancesMatrix(double *M);
    void SetData(unsigned int *CitiesData, unsigned int Pos, unsigned int N);
    int GetData(unsigned int *CitiesData);
    void DestroyList();
    // heuristics
    bool Perform2OPT();
    ...
    ...
    ...

    //!!!!!!! These pointers raises exception ???
    TCity *Head=NULL, *Tail=NULL, *Last; // Pointer to the head and tail of list
    double *Distance; // Pointer to distances matrix
    int Num; // Number of cities

    void DestroyList() {
         TCity *C=Head, *T;
         while (C!=Tail) {
     T=C;
     C=C->Next;
     delete T;
         }
         delete C;
    }

    void SetDistancesMatrix(double *M) {
         Distance=M;
    }

    // Main DLL function. We do not use any initializatoins
    BOOL APIENTRY DllMain( HANDLE hModule,
                          DWORD  ul_reason_for_call,
                          LPVOID lpReserved
         )
    {
       return TRUE;
    }

    void SetData(unsigned int *CitiesData, unsigned int Pos, unsigned int N) {
         TCity *C;
         Num=N;
         Head=new TCity;  Tail=new TCity;  Last=Head;
         Head->Data=0;  Tail->Data=0;
         for (unsigned int i=Pos; i<Pos+Num; i++) {
     C=new TCity;
     C->Data=CitiesData[i];
     C->Prev=Last;
     Last->Next=C;
     Last=C;
         }
         Tail->Prev=Last;      Last->Next=Tail;
    }

    int GetData(unsigned int *CitiesData) {
         int Idx=0;
         TCity *C=Head->Next;
         while (C!=Tail) {
     CitiesData[Idx++]=C->Data;
     C=C->Next;
         }
         return Idx-1;
    }


    // Performs 2-OPT herustics
    bool Perform2OPT() {
         TCity *I1, *I2, *J1, *J2;
         unsigned int TempData;
         bool Result=false;
         int Cnt1=0, Cnt2=0, Cnt3=0;
    Next:
         I1=Head->Next;
         do {
     I2=I1->Next;
     J1=I2->Next;
     do {
             J2=J1->Next;
           if ((Distance[I1->Data*Num+J1->Data]+Distance[I2->Data*Num+J2->Data])<
       (Distance[I1->Data*Num+I2->Data]+Distance[J1->Data*Num+J2->Data]))
           {
       while (I2!=J1) {
             TempData=I2->Data;
             I2->Data=J1->Data;
             J1->Data=TempData;
             I2=I2->Next; J1=J1->Prev;
             if (J1->Next==I2) break;
       }
       Result=true;
       goto Next;
           }
           J1=J2;
     } while ((J1!=Tail->Prev)&&J1->Next);
     I1=I2;
         } while (I1!=Tail->Prev->Prev);
         return Result;
    }

    Так выглядит модуль объявлений функций в библиотеке (VB.NET):
    Цитата

    Module heuristics
       Declare Sub SetDistancesMatrix Lib "heuristics32.dll" (ByRef M As Double(,))
       Declare Sub SetData Lib "heuristics32.dll" (ByRef CitiesData As Integer(), ByVal Pos As Integer, ByVal N As Integer)
       Declare Function GetData Lib "heuristics32.dll" (ByRef CitiesData As Integer()) As Integer
       Declare Sub DestroyList Lib "heuristics32.dll" ()

       Declare Function Perform2OPT Lib "heuristics32.dll" () As Byte
    ...
    ...
    ...
    End Module


    А это класс-интерфейс для работы с библиотекой (собственно проэкт VB.NET):
    Цитата

    Module TSPClass
       Public Class HeuristicsClass
           Private FCitiesNum As Integer   'Number of cities
           Private FCities As Integer()      'Array of cities indexes
           Private DistancesMatrix As Double(,) 'Matrix with distances between cities
           Private FDBName As String      'File name of database with cities data
           Private FTableName As String    'Name of table in database
           Private FOptimized As Boolean   'Optimized flag

           Public ReadOnly Property CitiesCount() [COLOR=blue]As Integer
           Public Property DBName() As String
           Public Property TableName() As String
             Public ReadOnly Property Optimized() As Boolean
           Public Function GetTourPoints(ByRef Data As Short()) As Boolean
           Public Function SetTourPoints(ByRef Data As Short()) As Boolean

           'This method reads table (specifyed by TableName property) from source database (name specifyed by DBName property)
           'and loads data from it for optimization. Fields MUST BE named as follows: "Index", "X", "Y".
           'If function succeeds, returned value is true, otherwise - false

           Public Function ReadSource() As Boolean
               Dim Result As Boolean = True    'Return value
    'Всякие объявления
               Try
    'Здесь я считываю массив из базы данных (как раз то, что я спрашивал в соседнем топике)
    'А вот тут пошли вызовы из DLL:

                   Call SetDistancesMatrix(DistancesMatrix)    'Set pointer to distances matrix
                   Call SetData(FCities, 0, N)                 'Set current sequence for optimization
               Catch DllEx As DllNotFoundException
                   MsgBox(DllEx.Message, MsgBoxStyle.Critical, "Error")
                   FCitiesNum = 0
                   Result = False
               Catch ex As Exception                          'If error occured ...
                   FCitiesNum = 0                              'Clear number of cities
                   Result = False                              'Return result - false (failed)
               Finally
                   DataReader.Close()
                   Connection.Close()
               End Try
               Return
    Result
           End Function

    'А это, господа, и виновник всех неудач (как я с себя все свалил) :)
           Function Perform_2OPT() As Boolean
               Try

                   FOptimized = Perform2OPT()
               Catch DllEx As DllNotFoundException
                   MsgBox(DllEx.Message, MsgBoxStyle.Critical, "Error")
               Catch e As NullReferenceException
                   MsgBox("Che za hren'???"+e.Message)
               End Try
               Return
    FOptimized
           End Function
    ...
    ...
    ...
           Public Sub New(ByVal DBN As String, ByVal TN As String)
               Dim Response As MsgBoxResult = MsgBoxResult.Retry
               FOptimized = False
               FCitiesNum = 0
               FDBName = DBN
               FTableName = TN
               While (Not ReadSource()) And Response = MsgBoxResult.Retry
                   Response = MsgBox("Error reading database", MsgBoxStyle.RetryCancel, "ERROR")
              End While
           End Sub

           Protected Overrides Sub
    Finalize()
               MyBase.Finalize()
           End Sub
       End Class


    P.S. Извините за такой объём, но иначе нельзя объяснить проблему.

    Спасибо за вимание.
      А почему нельзя использовать System.Collections.ArrayList? Скорее всего он использует оптимальные алгоритмы, и не особо уступает в скорости написанному.

      Или почему бы не сделать библиотеку managed dll?

      А гонять библиотеку под отладчиком пробовал? Именно библиотеку, а не программу.
        Здравствуйте!
        Дело в том, что стандартный класс работает медленно. Я тестировал и стандартный и мною написанный в среде VB.NET класс, хороших результатов это не дало. А на С++ я программу отлаживал и она работает.

        Неужели указатели в библиотеке не сохраняются? Как это может быть?
          1. Если используешь VS2003 - имеет смысл переписать на MC++ и не париться. А то можешь на интеропе потерять больше.
          2. Указатели маршалятся как IntPtr а не как Integer. Этот тип специально для этого и создан.
          Может баг еще где, извини, это просто в глаза бросилось.. времени нет :)
          Сообщение отредактировано: kl -
            То есть ты хочешь сказать, что необходимо поменять:
               Declare Sub SetData Lib "heuristics32.dll" (ByRef CitiesData As Integer(), ByVal Pos As Integer, ByVal N As Integer)
               Declare Function GetData Lib "heuristics32.dll" (ByRef CitiesData As Integer()) As Integer

            На:

               Declare Sub SetData Lib "heuristics32.dll" (ByVal CitiesData As IntPtr, ByVal Pos As Integer, ByVal N As Integer)
               Declare Function GetData Lib "heuristics32.dll" (ByVal CitiesData As IntPtr) As Integer

            ???
              Угу
                Спасибо за ответ, все понятно. Но:
                - Как мне послылать тогда массив 32-х битных значений?
                - А в самой библиотеке тоже надо получать как IntPtr?
                - И как его там конвертить в массив интов?

                Большое спасибо.

                С уважением, neutrino.
                  Цитата neutrino, 22.07.03, 20:06:15
                  Спасибо за ответ, все понятно. Но:
                  - Как мне послылать тогда массив 32-х битных значений?
                  - А в самой библиотеке тоже надо получать как IntPtr?
                  - И как его там конвертить в массив интов?
                  Большое спасибо.
                  С уважением, neutrino.

                  В библиотеке у тебя обычные указатели.
                  А про передачу массивов прочитай здесь. (последний ответ)
                  Сообщение отредактировано: kl -
                    Привет еще раз. Надеюсь я вас не замучил...

                    Ссылка оказалась на самом деле полезной. После того, как я ее прочитал, нашел и у себя в МСДН подходящий топик.

                    Назревает вопрос: а надо ли мне маршалить массив, если библиотеку я тоже написал в .NET Framework? Странно получается... Или язык С++ по определению у них "Unsafe" из-за указателей или еще чего...

                    Кстати, из того, что я прочитал в МСДН следует, что определение должно выглядеть так:
                    Declare Sub SetData Lib "heuristics32.dll" (ByRef <MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)>  CitiesData As Integer(), ByVal Pos As Integer, ByVal N As Integer)
                    ??? ??? ???
                      Так понятно, прочитай-ка про C++ with managed extensions. Особенно обрати внимание на __gc arrays. Возможно у тебя отпадет куча вопросов  и надобность в интеропе заодно.
                      Сообщение отредактировано: kl -
                        Большое спасибо господину kl за исчерпывающий ответ и помощь.
                          Я немного поторопился с выводами...

                          У меня ничего не вышло с этими __gc. Все время синтаксические ошибки. Вот так я писал:

                          double Distance __gc[,];

                          void SetDistancesMatrix(double M __gc[,]) {
                               Distance=M;
                          }

                          Да и такое определение не прокатывает:

                          void SetData(unsigned int CitiesData __gc[], unsigned int Pos, unsigned int N)

                          Как же нужно правильно писать?
                            Приведи ошибки-то, нет времени компилить.
                            Я надеюсь, ты с опцией /clr компилил?
                              Ну Ё! Ты хоть МСДН почитай что-ли!
                              __gc это storage класс, как static или register. Соответственно его надо указывать там где ДОЛЖЕН появляться storage-класс. Или, для __gc arrays ПЕРЕД словом new при выделении памяти:
                              ExpandedWrap disabled
                                <br>double array[]= [b]__gc[/b] new double[100]<br>


                              Ссылки в MSDN:
                              ms-help://MS.VSCC.2003/MS.MSDNQTR.2003APR.1033/vcmxspec/html/vcManagedExtensionsSpec_4_5.htm  - это __gc arrays

                              ms-help://MS.VSCC.2003/MS.MSDNQTR.2003APR.1033/vcmxspec/html/vcManagedExtensionsSpec_4.htm  - это по поводу __gc вообще

                              ms-help://MS.VSCC.2003/MS.MSDNQTR.2003APR.1033/vcmex/html/vcconMCOverview.htm  - это всё про managed extensions for C++
                                Цитата andrey, 30.07.03, 23:26:44
                                Ну Ё! Ты хоть МСДН почитай что-ли!
                                __gc это storage класс, как static или register. Соответственно его надо указывать там где ДОЛЖЕН появляться storage-класс. Или, для __gc arrays ПЕРЕД словом new при выделении памяти:
                                ExpandedWrap disabled
                                  <br>double array[]= __gc new double[100]<br>




                                __gc - это ключевое слово, говорящее о том, что объект будет размещен в управляемой куче (куче CLR). И синтаксис должен выглядеть вот так:
                                ExpandedWrap disabled
                                  <br>double array __gc[] = new double __gc[100];<br>

                                А причем тут например static я так и не понял
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0517 ]   [ 16 queries used ]   [ Generated: 27.04.24, 16:53 GMT ]