Существует полноценный интерфейс 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)