Недокументированное подключение к Maple библиотеке

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

SergeyM
Начинающий
Начинающий
 
Сообщения: 2
Зарегистрирован: 16.07.2007 (Пн) 0:28

Недокументированное подключение к Maple библиотеке

Сообщение SergeyM » 16.07.2007 (Пн) 0:56

Всем привет! Давайте усилим функциональность наших приложений.

Существует полноценный интерфейс OpenMaple для внешнего подключения библиотек Maple. Он реализован в виде доступа к классическим (не ActiveX) DLL языка Maple.
Проблема в том, что реализация его выполнена для VB6 путем надстройки доступа к DLL, сделанным как классический API.

Итак, пусть в системной папке имеется maplec.dll. (Установлен Maple)

Ставим задачу переработать файл maple.bas (находится в корневой папке Maple 9-11).

Заранее сообщаю, что запустить ядро Maple удалось, а вот с командой, которая проводит вычисления (из той же DLL) что-то не получается.

Привожу оригнальный кусок (от maple.bas) и мою интерпретацию его в VB.NET. ВСЕ ТАКИ МНЕ ДУМАЕТСЯ, ЧТО СТРОКА В MAPLE НОТАЦИИ ПЕРЕДАЕТСЯ НЕКОРРЕКТОНО! "Это я вперед забегаю!
Код: Выделить всё

Интерфейс собран на С и никакого отношения не имеет к ActiveX. А потом адаптирован к VB6.0 путем дополнительных ухищрений - надстройки в виде файла maple.bas, который собственно содержит декларации DLL и немного крутит со строками и байтами.
В ЭТОМ И ЕСТЬ ЗАДАЧА - ПЕРЕПИСАТЬ НЕ ВЕСЬ ДАЖЕ ФАЙЛ, А ХОТЯ БЫ САМЫЕ ВАЖНЫЕ ФУНКЦИИ ПОД НЕТ.

Вся в целом, эта штука называется OpenMaple для тех у кого есть запросите справку в Maple. Так что VB вызывает классическую DLL, собранную в С.
Само ядро Maple удалось запустить! То есть получен указатель на ядро, который входит передаваемым параметром во все остальные функции, которые и проводят вычисления. Вот, например функция EvalMapleStatement, получив такой указатель и строку в виде чистейшего Maple кода (например, "sin(x);")должна возвращать указатель на результат. При появлении ошибки возвращается ноль. Я измучался, мне уже и Maple не нужен :-), но причину установить - дело чести.
Итак,поехали
=================================================
VB 6.0 maple.bas file
Короче собственность maplesoft
=================================================
[code]
Public cb As MapleCallBack
Public kv As Long

'callback vector supplied to StartMaple
Type MapleCallBack
  lpTextCallBack        As Long
  lpErrorCallBack       As Long
  lpStatusCallBack      As Long
  lpReadLineCallBack    As Long
  lpRedirectCallBack    As Long
  lpStreamCallBack      As Long
  lpQueryInterrupt      As Long
  lpCallBackCallBack    As Long
End Type

Declare Function xStartMaple Lib "maplec.dll" Alias "_StartMaple@24" _
    (ByVal NumArgs As Integer, ByRef Arguments As Long, _
    ByRef mcb As MapleCallBack, ByRef user_data As Byte, _
    ByVal info As Long, ByRef error As Byte) As Long

Declare Function xEvalMapleStatement Lib "maplec.dll" Alias "_EvalMapleStatement@8" _
   (ByVal MKernelVector As Long, ByRef expr As Byte) As Long

'============================================
' StartMaple implementation stub
'============================================

Public Function StartMaple(ByVal NumArgs As Integer, ByRef Arguments() As String, ByRef mcb As MapleCallBack, ByRef user_data As Byte, ByRef ErrorMsg As String) As Long
    Dim i As Long
    Dim error_message(0 To 2048) As Byte
    ReDim args(0 To NumArgs) As Long
    Dim arg0() As Byte
    Dim MKernelVector As Long
    Dim allargs As String
    ReDim argoffset(0 To NumArgs) As Integer
    Dim conv_args() As Byte
   
    ' convert args to byte arrays
    allargs = ""
    argoffset(0) = 0
    arg0 = StrConv("mserver" + Chr$(0), vbFromUnicode)
    args(0) = VarPtr(arg0(0))
    For i = 1 To NumArgs
        allargs = allargs + Arguments(i) + Chr$(0)
        argoffset(i) = Len(allargs)
    Next i
    conv_args = StrConv(allargs, vbFromUnicode)
    For i = 1 To NumArgs
        args(i) = VarPtr(conv_args(argoffset(i - 1)))
    Next i
   
    error_message(0) = 0
    MKernelVector = xStartMaple(NumArgs + 1, args(0), cb, user_data, 0, error_message(0))
    ErrorMsg = StrConv(error_message, vbUnicode)
   
    StartMaple = MKernelVector
End Function

Public Function EvalMapleStatement(ByVal MKernelVector As Long, expr As String) As Long
    Dim xexpr() As Byte
    xexpr = StrConv(expr + Chr$(0), vbFromUnicode)
    EvalMapleStatement = xEvalMapleStatement(MKernelVector, xexpr(0))
End Function

В загрузке формы старт имеет вид:
Private Sub Form_Load()
Dim i As Integer
Dim error As String
   
    ' Dim args(0 To 1) As String
    Dim argv(1 To 2) As String
    argv(1) = "-i" ' Все что угодно здесь кажется работает
    argv(2) = "/home/myinit" ' И тут тоже

    ' Init callbacks
    cb.lpTextCallBack = 0 'GetProc(AddressOf TextCallBack)
    cb.lpErrorCallBack = 0 ' GetProc(AddressOf ErrorCallBack)
    cb.lpStatusCallBack = 0
    cb.lpReadLineCallBack = 0
    cb.lpRedirectCallBack = 0
    cb.lpQueryInterrupt = 0
    cb.lpCallBackCallBack = 0
   
   
    ' Start Maple
    kv = StartMaple(2, argv, cb, 0, error)
'Возможны варианты kv = StartMaple(2, argv, cb, 0, 0)
    If kv = 0 Then
        MsgBox "Error starting Maple: " + StrConv(error, vbUnicode), vbCritical, ""
        Unload Me
        End
     End If
     
     End Sub
'ErrorCallBack - для генерации сообщений об ошибках, возникающих в Maple - не принципиально.

Далее, считаем что-нибудь в виртуальном Maple-сеансе:

Private Sub Command1_Click()
Dim TestHandler As Long
TestHandler = EvalMapleStatement(kv, "f:=cos(x);")
' Все, если TestHandler не нулевой (ну вроде 34582134), значит в памяти сидит ответ на задачу. Как его достать, пока оставим - для этого другие функции используются.
[/code]


Следующим сообщением бросаю NET потуги!

===============================================
Все предыдущее можно найти в файле maple.bas в корневой папке maple. Детали интерфейса можно найти в С хедерах maplec.h  и еще парочке там же.
===============================================
Реализация подключения в NET
[code]
Module Module1
    Public cb As MapleCallBack
    Public kv As Integer
    Public MKernelVector As Integer

Declare Function xStartMaple Lib "maplec.dll" Alias "_StartMaple@24" _
        (ByVal NumArgs As Integer, _
        ByRef Arguments As Integer, _
        ByRef mcb As MapleCallBack, _
        ByRef user_data As Byte, _
        ByVal info As Integer, _
        ByRef UserError As Byte) As Integer

Declare Auto Function xEvalMapleStatement Lib "maplec.dll" Alias "_EvalMapleStatement@8" _
       (ByVal MKernelVector As Integer, ByRef expr As Byte) As Integer

    Public Function StartMaple(ByVal NumArgs As Integer, ByRef Arguments() As String, ByRef mcb As MapleCallBack, ByRef user_data As Byte, ByRef ErrorMsg As String) As Long
        Dim i As Integer
        Dim error_message(0 To 2048) As Byte
        Dim args(0 To NumArgs) As Integer 'Long
        Dim arg0() As Byte

        Dim allargs As String
        Dim argoffset(0 To NumArgs) As Integer
        Dim conv_args() As Byte

        'Dim cb As MapleCallBack

        ' convert args to byte arrays
        allargs = ""
        argoffset(0) = 0
        arg0 = System.Text.UnicodeEncoding.Unicode.GetBytes( _
           "mserver" + Chr(0))


        'args(0) = VarPtr(arg0(0))
        Dim handle As GCHandle = GCHandle.Alloc(arg0(0), GCHandleType.Pinned)
        Dim address As Integer = handle.AddrOfPinnedObject.ToInt32
        args(0) = address
        'handle.Free()

        For i = 0 To NumArgs - 1
            allargs = allargs + Arguments(i) + Chr(0)
            argoffset(i) = Len(allargs)
        Next i
        conv_args = System.Text.UnicodeEncoding.Unicode.GetBytes(allargs)
        For i = 1 To NumArgs
            Dim handle_01 As GCHandle = GCHandle.Alloc(conv_args(argoffset(i - 1)), GCHandleType.Pinned)
            Dim address_01 As Integer = handle_01.AddrOfPinnedObject.ToInt32
            args(i) = address_01
           
        Next i

        error_message(0) = 0
        MKernelVector = xStartMaple(NumArgs + 1, args(0), cb, user_data, 0, error_message(0))
        ErrorMsg = System.Text.UnicodeEncoding.Unicode.GetString(error_message)

        StartMaple = MKernelVector
    End Function

' В форме ==========================
Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
   
Dim argv(0 To 2) As String
        argv(1) = "-i"
        argv(2) = "/home/myinit"



        ' Init callbacks
        cb.lpTextCallBack = 0   'msd.DynamicInvoke(2, MAPLE_TEXT_OUTPUT, 4)   'GetProc(AddressOf TextCallBack)
        cb.lpErrorCallBack = 0  ' AddressOf ErrorCallBack
        cb.lpStatusCallBack = 0
        cb.lpReadLineCallBack = 0
        cb.lpRedirectCallBack = 0
        cb.lpQueryInterrupt = 0
        cb.lpCallBackCallBack = 0

        ' Start Maple
        kv = StartMaple(2, argv, cb, 0, 0)
End Sub

Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
       
        Dim HeandlerMapleCalc As Integer
        HeandlerMapleCalc = EvalMapleStatement(kv, "sin(x);")
        TextBox2.Text = HeandlerMapleCalc
    End Sub


[/code]

Вход в DLL есть, результат ошибочный!
Указатель нулевой.


Вход в DLL есть, результат ошибочный!
Указатель нулевой.

ПОМОГИТЕ ДРУГИ!!!!!!!!!!

Кстати, подскажите пожалуйста полный аналог строки VB6 в VB.NET
Dim xexpr() As Byte
xexpr = StrConv(expr + Chr$(0), vbFromUnicode)

SergeyM
Начинающий
Начинающий
 
Сообщения: 2
Зарегистрирован: 16.07.2007 (Пн) 0:28

Решение найдено

Сообщение SergeyM » 16.07.2007 (Пн) 4:48

+++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++
СУПЕР!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :lol: :lol: :lol:
=================================================
=================================================

Проблема решена!
Да здравствуют русские программисты!
Да здравствует компания Maplesoft с ее математическим движком!!!!

А то в документации Maple. Это не работает в VB.NET и прочее!


ИТАК, КОЛЛЕГИ! БУДЬТЕ ОСТОРОЖНЫ!
Классическая конструкция VB6.0
xexpr = StrConv(expr + Chr$(0), vbFromUnicode)
конвертирует строку в bytes of ANSII реализации.
Maple также работает с ANSII реализацией.
Поэтому просто была необходима дополнительная конвертация, реализуемая в VB.NET семейством
System.Text.UnicodeEncoding.=========

По прежнему восхищаюсь VB.NET(VB6). И Maple конечно тоже!!!

Вся мощь ядра Maple в Ваших руках господа.
Конечно, надо бы переписать весь этот интерфейс под NET - он же платформенно независимый.
Хороший полноценный интерфейс с классами (ох не люблю я эту терминологию, семейство как то по-домашнему звучит. А на классы у ресского человека аллергия).
Но это уже будет совсем другая история. Наверное этим и займусь как следкет.

Всем СПАСИБО!
=================================================
:lol:


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 71

    TopList