Problem: DLL unter BMax (spez. MS Speech API)- gelöst

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

Sokrates696

Betreff: Problem: DLL unter BMax (spez. MS Speech API)- gelöst

BeitragDo, Jul 24, 2008 13:13
Antworten mit Zitat
Benutzer-Profile anzeigen
*************************************************************************************

UPDATE : "Hab den Vorschlag von ChristianK" (- Vielen Dank -) Code aktualisiert

*************************************************************************************

Holla,

bastel seit einiger Zeit daran herum, diese SAPIDLL.dll (*1*) unter Blitzmax einzubinden und natürlich zum laufen zu bringen Smile .

Laut der Webseite(*1*) ist die DLL als " 4. The SAPIDLL API SDK. All API is STDCALL " "compiliert", insofern dürfte dies den Vorrausetzungen entsprechen für die DLL-Einbindung unter Blitzmax. (so weit ich das dem englisch und deutschen Forum entnehmen konnte)

Hab mal meinen bisherige Code angefügt. Die ist jetzt ein Version die scheinbar läuft - zumindest was die Existenz der Funktion und dem Laden der Dll angeht. Ich hatte, aber auch schon andere Varianten programmiert , die die üblich Memory Violation und nicht reference- Meldungen hervorbrachten...(Extern als Module einbinden...)

Unter Purebasic (*2*) existiert ( - mit der gleichen DLL(?- nicht ganz sicher!)) ein Sourcecode der einwandfrei funktioniert.

Unter Blitz3d (*3*) gibt es unter "So to Speak" ein DLL und Source, mit dieser Variante hab ich angefang eine Portierung hinzubekommen...

Ich habe es mit beiden DLL's versucht, aber anscheinend produziere ich da nur Müll.. (Auf "Spam-Source" hab jetzt mal verzichtet Wink. Mein "Wissen" basiert auf den Tutorials der Foren (D/E))

In der Hoffnung, daß mir einer der Gurus aus diesem Forum ein Tip geben könnte, wie ich jetzt dieses Ding zum laufen bringen kann bzw. wie es jetzt weitergeht.


Vielen Dank im Voraus

Ansonst sind die Quellen vielleicht interessant Smile

Quellen:
-----------
(*1*) http://wtwsoft.narod.ru/SAPIDLL/sapidlle.htm
(*2*) http://www.purebasic.fr/german...6ff3bd9fa2
(*3*) http://www.sergiomarcello.com/



Code: [AUSKLAPPEN]


 
Strict
Import pub.win32
'DebugStop()

' ********** Variablen Def:

Local DllName:String, DllHandle:Int

'**********  DLL-Def und Laden


DllName  = "SAPIDLL.dll"
DllHandle  = LoadLibraryA(DllName)

' ********** Testen ob's geladen wird

If DllHandle = 0
   Print "Dll konnte nicht geladen werden"
   End
EndIf


Global  jpCreateSpeech() "Win32" = GetProcAddress(DllHandle,"CreateSpeech")

Global  jpGetEngineInfo(EngineName$z) "Win32" = GetProcAddress(DllHandle,"GetEngineInfo")

Global  jpGetEngines (EngineName$z) "Win32" = GetProcAddress(DllHandle,"GetEngines")

Global  jpSelectEngine (Number: Int) "Win32" = GetProcAddress(DllHandle,"SelectEngine")


Global jpPSpeak (Text: String) "Win32" = GetProcAddress(DllHandle,"PSpeak")


'  ************   Schaue ob Funktion vorhanden ist :

Function FunctionExists(func:Byte Ptr)
   If func <> Null
      Return True
   EndIf
  Return False
End Function


If FunctionExists(jpCreateSpeech)
   Print "Funktion CreateSpeech existiert"
Else
   Print "Funktion CreateSpeech konnte nicht aufgerufen werden"
EndIf

If FunctionExists(jpSelectEngine)
   Print "Funktion jpSelectEngine existiert"
Else
   Print "Funktion jpSelectEngine konnte nicht aufgerufen werden"
EndIf

If FunctionExists(jpPSpeak)
   Print "Funktion jpPSpeak existiert"
Else
   Print "Funktion jpjpPSpeak konnte nicht aufgerufen werden"
EndIf


'**********     Hauptprogramm


Print "TEST 1 START"
If  jpCreateSpeech() = 0
     Print "CreateSpeech hat funktioniert "
EndIf


Rem
************************************************************************************
 
Aufrufe aus dem Delphi - Sample - Schnittstellen : siehe Webseite *1*

Function  CreateSpeech:HResult;stdcall;external 'SAPIDLL.DLL' name 'CreateSpeech';
procedure DestroySpeech;stdcall;external 'SAPIDLL.DLL';
procedure Speak( Text : String);stdcall;external 'SAPIDLL.DLL';
procedure SelectEngine(EngineName: String);stdcall;external 'SAPIDLL.DLL' name 'SelectEngine';
Function  GetEngineInfo(EngineName: String; Var Info: TEngineInfo):Byte;stdcall;external 'SAPIDLL.DLL';
Function  GetEngines:TStrings;stdcall;external 'SAPIDLL.DLL' name 'GetEngines';
Function  GetEnginesCount:word;stdcall;external 'SAPIDLL.DLL';
Function  GetPitch: Word;stdcall;external 'SAPIDLL.DLL';
Function  GetSpeed: dword;stdcall;external 'SAPIDLL.DLL';
Function  GetVolume: dword;stdcall;external 'SAPIDLL.DLL';
procedure SetPitch(Const Value: Word);stdcall;external 'SAPIDLL.DLL';
procedure SetSpeed(Const Value: dword);stdcall;external 'SAPIDLL.DLL';
procedure SetVolume(Const Value: dword);stdcall;external 'SAPIDLL.DLL';
Function  GetMaxPitch: Word;stdcall;external 'SAPIDLL.DLL';
Function  GetMaxSpeed: dword;stdcall;external 'SAPIDLL.DLL';
Function  GetMaxVolume: dword;stdcall;external 'SAPIDLL.DLL';
Function  GetMinPitch: Word;stdcall;external 'SAPIDLL.DLL';
Function  GetMinSpeed: dword;stdcall;external 'SAPIDLL.DLL';
Function  GetMinVolume: dword;stdcall;external 'SAPIDLL.DLL';
Procedure Pause;stdcall;external 'SAPIDLL.DLL';
Procedure Resume;stdcall;external 'SAPIDLL.DLL';
Procedure Stop;stdcall;external 'SAPIDLL.DLL';
//
procedure PSpeak( Text: LPCTSTR );stdcall;external 'SAPIDLL.DLL';
procedure PSelectEngine(EngineName: LPCTSTR);stdcall;external 'SAPIDLL.DLL';
procedure PSelectEngineNumber(EngineNumber: word);stdcall;external 'SAPIDLL.DLL';
Function  PGetEngines( number : word):LPCTSTR;stdcall;external 'SAPIDLL.DLL';

procedure RegistOnStart(CallbackAddr: TSpeechEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnPause(CallbackAddr: TSpeechEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnResume(CallbackAddr: TSpeechEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnStop(CallbackAddr: TSpeechEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnUserStart(CallbackAddr: TSpeechEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnUserStop(CallbackAddr: TSpeechEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnPosition(CallbackAddr: TPositionEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnSpeed(CallbackAddr: TPositionEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnVolume(CallbackAddr: TPositionEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnPitch(CallbackAddr: TPositionEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnSelectEngine(CallbackAddr: TEngineEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnStatusChange(CallbackAddr: TSpeechEvent);stdcall;external 'SAPIDLL.DLL';
procedure RegistOnError(CallbackAddr: TErrorEvent);stdcall;external 'SAPIDLL.DLL';


' Andere Programmm zur DLL-einbindung



Strict
Framework brl.blitz

Global Variable

Local Kernel32 = LoadLibraryW ( "Kernel32.dll" )
Local GetModuleHandleExW ( Flags , Name:Byte Ptr , ModHandle Ptr ) "Win32" = GetProcAddress ( Kernel32 , "GetModuleHandleExW" )
Local ModHandle
If GetModuleHandleExW ( 6 , Varptr Variable , Varptr ModHandle )
  WriteStdout "The memory used for this variable is located in the following module: " + ModHandle + "~n"
EndIf
FreeLibrary Kernel32

Extern "Win32"
  Function LoadLibraryW ( Name$w )
  Function GetProcAddress:Byte Ptr ( Library , Name$z )
  Function FreeLibrary ( Library )
EndExtern

End Rem
 
  • Zuletzt bearbeitet von Sokrates696 am Do, Jul 31, 2008 10:00, insgesamt 4-mal bearbeitet
 

ChristianK

BeitragDo, Jul 24, 2008 14:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab mir deinen Code mal angeschaut und mir sind ein paar Dinge aufgefallen:

Function Pointer solltest du immer global deklarieren, sonst kannst du sie nicht innerhalb anderer Funktionen verwenden.
In der Funktion FunctionExists machst du einen Int aus Byte Ptr. Vergleiche da besser den Zeiger mit Null.
Beim Laden von jpSelectEngine musst du das "@4" hinter dem Funktionsnamen weglassen.
AdvanceLcd
Intel Core 2 Duo 3.2 GHz, 4 GB RAM, GeForce 8800 GTX | MacBook Pro 15,4″ Intel Core 2 Duo 2.4 GHz, 2 GB RAM, GeForce 8600M GT
 

Peak7810

BeitragSa, Jul 26, 2008 10:36
Antworten mit Zitat
Benutzer-Profile anzeigen
da hab ich auch gleichmal eine frage.
für inline c++, wie muss man so ein stück code komplett für den Befehl Code: [AUSKLAPPEN]
FreeLibraryAndExitThread
aussehen?

brauch das dringend.

BtbN

BeitragSa, Jul 26, 2008 11:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Es gibt in Bmax kein inline-C++
 

Peak7810

BeitragSa, Jul 26, 2008 11:09
Antworten mit Zitat
Benutzer-Profile anzeigen
aber wenns gehen würde, ich muss so ein verdammtes fenster schliessen, was geöffnet wurde.
ist ein dx render fenster.

wie müsste der c++ code aussehen, wenns inline geben würde?

need help
 

Sokrates696

Betreff: Jetzt mal mit der SAPIDLL von Purebasic

BeitragMi, Jul 30, 2008 19:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Holla,

so hab mich mal mit dem Purebasic-Variante beschäftigt (s.o.)

" Unhandled Exception: Attempt to call uninitalized function pointer. "

End of the Road ? Also ist es nicht möglich von Blitzmax auf eine DLL zuzugreifen. Ich weiss dass es offizielle sowieso nicht vorgesehen ist, aber ....


Code: [AUSKLAPPEN]

Strict

Global ThisDLL = LoadLibraryA("SAPIDLL.dll")
'Note that you do not add the .DLL to the end of the library name

If ThisDLL=0 Then Print "Can't load DLL" End;

Global PCreateSpeech: Int (S2:Int) "win32" = GetProcAddress(ThisDLL, "CreateSpeech")

Global PSelectEngineNumber:Byte Ptr (S1: Byte Ptr ) "win32" = GetProcAddress(ThisDLL, "PSelectEngineNumber@4")
Global PSpeak:String (Str:String )  "win32" = GetProcAddress(ThisDLL, "PSelectEngineNumber@4")   


Local bpString1:String

Local bpResult:String

Local sString1:String

Local sResult:String

Local DD: Byte Ptr
Local Zahl:String
Zahl ="1"

PCreateSpeech(1)

DD = Zahl.ToCString()
PSelectEngineNumber(DD)

bpResult = Pspeak("Hallo")

 

ChristianK

BeitragMi, Jul 30, 2008 22:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie gesagt, du musst das @4 weg lassen. Wink
Außerdem lädst du sowohl für PSelectEngineNumber, als auch für PSpeak die gleiche Funktion aus der DLL, nämlich PSelectEngineNumber. Für die zweite sollte es wohl PSpeak sein?
Und statt dem Parameter str:String solltest du str$z angeben, denn BlitzMax hat seine eigenen Unicode-Strings und ich nehme mal an, dass die DLL C-Strings erwartet.
AdvanceLcd
Intel Core 2 Duo 3.2 GHz, 4 GB RAM, GeForce 8800 GTX | MacBook Pro 15,4″ Intel Core 2 Duo 2.4 GHz, 2 GB RAM, GeForce 8600M GT
 

Sokrates696

BeitragMi, Jul 30, 2008 23:03
Antworten mit Zitat
Benutzer-Profile anzeigen
ChristianK hat Folgendes geschrieben:
Wie gesagt, du musst das @4 weg lassen. Wink

Außerdem lädst du sowohl für PSelectEngineNumber, als auch für PSpeak die gleiche Funktion aus der DLL, nämlich PSelectEngineNumber. Für die zweite sollte es wohl PSpeak sein?



- Embarassed - Oh Herr gib mir Hirn oder vielleicht besser ein verdammt guten Ventilator, verdammt warm hier peinlich. naja man sollte nicht bei 35 Grad in der Wohnung programmieren und nicht mal eben zwischen Tür und Angel......

Zitat:

Und statt dem Parameter str:String solltest du str$z angeben, denn BlitzMax hat seine eigenen Unicode-Strings und ich nehme mal an, dass die DLL C-Strings erwartet.



Oh ! Sehr interessant - ich hatte dieses Zeichen zwar schon mal gesehen, aber keine Erklärung dazu gefunden..... Vielen Dank
 

Sokrates696

Betreff: Die Lösung mit Purebasic funzt :-)

BeitragDo, Jul 31, 2008 9:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Holla,

nach dem sich wahrscheinlich - vermutlich- , daß halbe Forum totgelacht hat über mein Problem hab ich es dann doch endlich geschafft Smile - Man muss, wenn man keinen Plan und keine Doku hat einfach lange genug puzzeln....

Diese Version läuft mit der Purebasic "SAPIDLL.dll" (s.o) . Vielen Dank nochmal an ChristianK. und all die anderen im Forum . Der letzte Lösungshinweis befandt sich im englischen Forum.


Code: [AUSKLAPPEN]


Strict

Global ThisDLL = LoadLibraryA("SAPIDLL.dll")

If ThisDLL=0 Then Print "Can't load DLL" End;

Global PCreateSpeech: Int (S2:Int) "win32" = GetProcAddress(ThisDLL, "CreateSpeech")

Global PSelectEngineNumber:Byte  (S1: Byte  ) "win32" = GetProcAddress(ThisDLL, "PSelectEngineNumber")

Global PSpeak(str$z) "win32" = GetProcAddress(ThisDLL, "PSpeak")   


Local mystr:String="the really cool test string"
Local strptr:Byte Ptr=mystr.ToCString()
Local bpResult:String


PCreateSpeech(1)
PSelectEngineNumber(1)

bpResult = Pspeak(mystr)

WaitKey

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group