Aktuelle Zeit: 22.05.2013 23:40

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Amibroker AFL - Plugin
BeitragVerfasst: 07.08.2010 00:44 
Offline

Registriert: 29.08.2004 16:58
Hallo,

hab mich gerade mit der Plugin-Schnittstelle vom Amibroker (Börsensoftware von http://www.amibroker.com) beschäftigt.
Ich will ein AFL-Plugin schreiben, und zumindest alles was ich brauche funktioniert erstmal.
Leider habe ich aber nicht das "SiteInterface" zum laufen bekommen welches so in C/C++ definiert ist:

Code:
struct SiteInterface
{
            int         nStructSize;
            int         (*GetArraySize) (void);      
            float *      (*GetStockArray)( int nType );
            AmiVar      (*GetVariable) ( const char *pszName );
            void      (*SetVariable) ( const char *pszName, AmiVar newValue );
            AmiVar      (*CallFunction) ( const char *szName, int nNumArgs, AmiVar *ArgsTable );
            AmiVar      (*AllocArrayResult) (void);
            void *      (*Alloc) (unsigned int nSize);
            void      (*Free) (void *pMemory);
            DATE_TIME_INT* (*GetDateTimeArray) (void);     // new in 5.30
};


ich habe das draus gemacht:

Code:
Structure SiteInterface
  nStructSize.l
  *GetArraySize.pGetArraySize
  *GetStockArray.pGetStockArray
  *GetVariable.pGetVariable
  *SetVariable.pSetVariable
  *mCallFunction.pCallFunction
  *AllocArrayResult.pAllocArrayResult
  *Alloc.pAlloc
  *Free.pFree
  *GetDateTimeArray.pGetDateTimeArray
EndStructure


es kommt aber zu Speicherfehlern und ich bekomme auch kein Pointer zurück wenn ich versuche auf eine
Funktion zuzugreifen. z.B. selbst ein "einfaches" GetVariable funktioniert einfach nicht, und wird mit Speicherfehlern vom Amibroker quittiert.

Hier mal ein Code eines AFL-Plugins, welches für Amibroker die Funktion "BTS_Test" zur Verfügung stellt.
Hier ist sicherlich "überflüssiges" aus Vergangenen Tests drin, und man könnte es sicherlich ordentlicher schreiben,
aber grundlegend funktionierts erstmal - bis leider auf das "SiteInterface"

Code:
#PLUGIN_VERSION = 10000
#PLUGIN_NAME = "Test"
#VENDOR_NAME = "VoSs2o0o"

#NumberofFunctions = 1

Enumeration
  #PLUGIN_TYPE_AFL = 1
  #PLUGIN_TYPE_DATA
  #PLUGIN_TYPE_AFL_AND_DATA
  #PLUGIN_TYPE_OPTIMIZER
EndEnumeration

Enumeration
  #VAR_NONE
  #VAR_FLOAT
  #VAR_ARRAY
  #VAR_STRING
  #VAR_DIS
EndEnumeration

Structure AmiVar
  type.l
  StructureUnion
    val.f
    *mArray.f[0]
    *string.STRING
    *disp.l
  EndStructureUnion
EndStructure

Structure PluginInfo
  nStructSize.l     ;// this is SizeOf( struct PluginInfo )
  nType.l           ; // plug-in type currently 1 - indicator is the only one supported
  nVersion.l        ; // plug-in version coded to int as MAJOR*10000 + MINOR * 100 + RELEASE
  nIDCode.l         ;// ID code used to uniquely identify the data feed (set it to zero for AFL plugins)
  szNname.s{64}     ;// long name of plug-in displayed in the Plugin dialog
  szVendor.s{64}    ;;// name of the plug-in vendor
  nCertificate.l    ;// certificate code - set it to zero for private plug-ins
  nMinAmiVersion.l ;// minimum required AmiBroker version (should be >= 380000 -> AmiBroker 3.8)
EndStructure

Prototype.l pGetArraySize()
Prototype.f pGetStockArray(nType.l)
Prototype.l pGetVariable(*pszName.STRING)
Prototype.l pSetVariable(*pszName.s, *newValue.AmiVar)
Prototype.l pCallFunction(szName.s, nNumArgs.l, *ArgsTable.AmiVar)
Prototype.l pAllocArrayResult()
Prototype.l pAlloc(nSize.l)
Prototype.l pFree(*pMemory)
Prototype.q pGetDateTimeArray()

Structure SiteInterface
  nStructSize.l
  *GetArraySize.pGetArraySize
  *GetStockArray.pGetStockArray
  *GetVariable.pGetVariable
  *SetVariable.pSetVariable
  *mCallFunction.pCallFunction
  *AllocArrayResult.pAllocArrayResult
  *Alloc.pAlloc
  *Free.pFree
  *GetDateTimeArray.pGetDateTimeArray
EndStructure

Structure FARRAY
  f.f[0]
EndStructure

Structure AMIARRAY
  ami.AmiVar[0]
EndStructure

Prototype.l pFunction(NumArgs.l, Array *ArgsTable.Amivar(1))
Structure FunDesc
  Function.l
  ArrayQty.b
  StringQty.b
  FloatQty.b
  DefaultQty.b
  *DefaultValues.FARRAY
EndStructure

Structure FunctionTag
  Name.STRING
  Descript.FunDesc
EndStructure

ProcedureDLL AttachProcess(Instanz.l)
  Global Dim FunctionTable.FunctionTag(#NumberofFunctions )
  Global Dim *myArgs.Amivar(0)
  Global *gpinterface.SiteInterface
  Global *erg.AmiVar
  *erg.AmiVar = AllocateMemory(1000)
 
  Global strParam1.STRING
EndProcedure

ProcedureCDLL.l GetPluginInfo(*pinfo.Plugininfo)

  *pinfo\nStructSize = SizeOf(PluginInfo)
  *pinfo\nType = #PLUGIN_TYPE_AFL
  *pinfo\nVersion = #PLUGIN_VERSION
  *pinfo\nIDCode = 0
  *pinfo\szNname = #PLUGIN_NAME
  *pinfo\szVendor = #VENDOR_NAME
  *pinfo\nCertificate = 0
  *pinfo\nMinAmiVersion = 530000
  ProcedureReturn 1
EndProcedure

ProcedureCDLL.l Init()

  ProcedureReturn 1
EndProcedure

ProcedureCDLL.l Release()

  ProcedureReturn 1
EndProcedure

ProcedureCDLL.l SetSiteInterface(*pinterface.SiteInterface)
  *gpinterface = *pinterface
  ProcedureReturn 1
EndProcedure


ProcedureC.l BTS_Test(NumArgs.l, *pArgsTable.AmiVar)
   
  MessageRequester("NumArgs", Str(NumArgs.l))
  If NumArgs.l > 0
    ReDim *myArgs.Amivar(NumArgs.l - 1)
    For i=0 To NumArgs.l - 1
      *myArgs(i) = *pArgsTable + (i*SizeOf(AmiVar))
     
      MessageRequester("CurrentArg", Str(i))
      MessageRequester("type", Str(*myArgs(i)\type))
      MessageRequester("val", Str(*myArgs(i)\val))
    Next
  EndIf

;######################################

 
  ProcedureReturn 1
EndProcedure



ProcedureCDLL.l GetFunctionTable(*ppFunctionTable)

  FunctionTable(0)\Name\s = "BTS_Test"
  FunctionTable(0)\Descript\Function = @BTS_Test()
  FunctionTable(0)\Descript\ArrayQty = 0
  FunctionTable(0)\Descript\StringQty = 0
  FunctionTable(0)\Descript\FloatQty = 0
  FunctionTable(0)\Descript\DefaultQty = 3
 
  *FunctionTable_DefaultValues.FARRAY = AllocateMemory(FunctionTable(0)\Descript\DefaultQty)
  *FunctionTable_DefaultValues\f[0] = 1
  *FunctionTable_DefaultValues\f[1] = 2
  *FunctionTable_DefaultValues\f[2] = 5
 
  PokeL(@FunctionTable(0)\Descript\DefaultValues, *FunctionTable_DefaultValues)
  PokeL(*ppFunctionTable, @FunctionTable(0))
 
  ProcedureReturn #NumberofFunctions
EndProcedure



Ich hoffe das jemand weiterhelfen kann bezüglich des "siteinterfaces"
PS: Das Amibroker "ADK" gibts auf der Downloadseite von Amibroker.com, und enthält eine Anleitung und
C/C++ Beispielcodes wie ein solch ein Plugin zu schreiben ist.

_________________
ActiveXInterfaceImporter und ActiveXLibrary


Nach oben
 Profil  
 
 Betreff des Beitrags: Re: Amibroker AFL - Plugin
BeitragVerfasst: 07.08.2010 01:09 
Offline
Benutzeravatar

Registriert: 08.09.2004 08:21
Wohnort: Porada Ninfu
auf Crosspostings solltest man der Fairness halber hinweisen:

http://www.purebasic.fr/english/viewtopic.php?f=13&t=43168

_________________
"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." - Martin Golding

PureBasic FAQ
PureBasic Projekthosting


Nach oben
 Profil  
 
 Betreff des Beitrags: Re: Amibroker AFL - Plugin
BeitragVerfasst: 07.08.2010 13:26 
Offline
Benutzeravatar

Registriert: 24.11.2004 13:12
Wohnort: Germany
Du must ein Interface anlegen und nicht eine Struktur. In einer Funktion in einen Interface ist immer der erste Parameter ein Pointer auf das eigene Objekt.
Must Dich also erst mal mit objektorientierte Programmierung beschäftigen.

Such erst mal im Forum wie das mit Interfaces funktioniert.

Ein ansatz ist schon mal hier.
http://www.purebasic.fr/german/viewtopic.php?f=8&t=22863&p=277062&hilit=scriptcontrol#p277062

FF :!:

_________________
Alles ist möglich, fragt sich nur wie...
OOP-Precompiler / OPC-Helper DLL / Visual Generate Deluxe v5.x / MyBackup v1.x
PB v3.30 / v5.00 - OS Window 7 Pro. (X64) / Window XP Pro. (X86) / Suse 11.1
Downloads umgestellt auf WebAccess


Nach oben
 Profil  
 
 Betreff des Beitrags: Re: Amibroker AFL - Plugin
BeitragVerfasst: 07.08.2010 13:55 
Offline
Benutzeravatar

Registriert: 28.07.2005 12:39
Nur weil das Ding Interface heisst, muss es noch lange nix mit den PB Interface zu tun haben.

In dem c++ Beispiel ist alles auf cdecl gestellt, versuch daher mal mit PrototypeC.

_________________
Suche


Nach oben
 Profil  
 
 Betreff des Beitrags: Re: Amibroker AFL - Plugin
BeitragVerfasst: 07.08.2010 22:54 
Offline

Registriert: 29.08.2004 16:58
Richtig, es wird durch Structure und Prototype ein Interface emuliert,
und heute Morgen habe ich genau das gesehen was edel schreibt:

Richtig da gehört PrototypeC hin, da alles "cdecl" ist (immer diese "Schusslichkeitsfehler...." )

Da aber zusätzlich hier kein Pointer als Ergebnis zurückgegeben wird, sondern direkt die Struktur
(was in Purebasic leider nicht möglich ist),
werd ich erst morgen oder Montag einen vollständig funktionierenden Code posten.

Werde mal mit Poke testen, und zur Not ein Quad "missbrauchen" da es ja nur 8 Byte sind....

Trotzdem, danke für die schnelle Hilfe.
Bei dieser ganzen C-Pointer Wurschtelei sieht man irgendwann den Wald vor lauter Bäumen nicht mehr...

PS: weiter unten war auch noch ein Fehler bei der Speicher-Allocation...

_________________
ActiveXInterfaceImporter und ActiveXLibrary


Nach oben
 Profil  
 
 Betreff des Beitrags: Re: Amibroker AFL - Plugin
BeitragVerfasst: 08.08.2010 09:27 
Offline
Benutzeravatar

Registriert: 28.07.2005 12:39
Versuch es mal so :
Code:
ProcedureCDLL.l SetSiteInterface(*pinterface.Integer)
  *gpinterface = *pinterface\i
  ProcedureReturn 1
EndProcedure

_________________
Suche


Nach oben
 Profil  
 
 Betreff des Beitrags: Re: Amibroker AFL - Plugin
BeitragVerfasst: 08.08.2010 14:20 
Offline

Registriert: 29.08.2004 16:58
Danke edel, aber es geht um die Rückgabe-Ergebnisse der Funktionen des "SiteInterfaces".
Die Funktionen liefern teilweise eine "AMIVAR" Struktur zurück.
Leider mag Purebasic keine Strukturen als Rückgabeparameter. Ich habe nun ein ".q" zur Hilfe genommen,
da die AMIVAR Struktur glücklicherweise "nur" 8 Bytes benötigt.
(Da wo das "mCallFunction" bzw das "Getvariable" aufgerufen wird).

Vielleicht gibts ja hier noch ein Trick wie man das "besser" lösen kann - wahrscheinlich ist das aber normal so, da der Amibroker-Programmierer ebenfalls C/C++ an dieser Stelle ein wenig "überstrapaziert" hat......

Hier also ein vollständig funktionierender Code:

Code:
#PLUGIN_VERSION = 10000
#PLUGIN_NAME = "Test"
#VENDOR_NAME = "VoSs2o0o"

#NumberofFunctions = 1

Enumeration
  #PLUGIN_TYPE_AFL = 1
  #PLUGIN_TYPE_DATA
  #PLUGIN_TYPE_AFL_AND_DATA
  #PLUGIN_TYPE_OPTIMIZER
EndEnumeration

Enumeration
  #VAR_NONE
  #VAR_FLOAT
  #VAR_ARRAY
  #VAR_STRING
  #VAR_DIS
EndEnumeration

Structure AmiVar
  type.l
  StructureUnion
    val.f
    *mArray.FARRAY[0]
    *string.STRING
    *disp.l
  EndStructureUnion
EndStructure

Structure PluginInfo
  nStructSize.l     ;// this is SizeOf( struct PluginInfo )
  nType.l           ; // plug-in type currently 1 - indicator is the only one supported
  nVersion.l        ; // plug-in version coded to int as MAJOR*10000 + MINOR * 100 + RELEASE
  nIDCode.l         ;// ID code used to uniquely identify the data feed (set it to zero for AFL plugins)
  szNname.s{64}     ;// long name of plug-in displayed in the Plugin dialog
  szVendor.s{64}    ;;// name of the plug-in vendor
  nCertificate.l    ;// certificate code - set it to zero for private plug-ins
  nMinAmiVersion.l ;// minimum required AmiBroker version (should be >= 380000 -> AmiBroker 3.8)
EndStructure

PrototypeC.l pGetArraySize()
PrototypeC.l pGetStockArray(nType.l)
PrototypeC.q pGetVariable(*pszName.s)
PrototypeC.l pSetVariable(*pszName.s, *newValue.AmiVar)
PrototypeC.q pCallFunction(szName.s, nNumArgs.l, *ArgsTable.AmiVar)
PrototypeC.q pAllocArrayResult()
PrototypeC.l pAlloc(nSize.l)
PrototypeC.l pFree(*pMemory)
PrototypeC.q pGetDateTimeArray()

Structure SiteInterface
  nStructSize.l
  *GetArraySize.pGetArraySize
  *GetStockArray.pGetStockArray
  *GetVariable.pGetVariable
  *SetVariable.pSetVariable
  *mCallFunction.pCallFunction
  *AllocArrayResult.pAllocArrayResult
  *Alloc.pAlloc
  *Free.pFree
  *GetDateTimeArray.pGetDateTimeArray
EndStructure

Structure FARRAY
  f.f[0]
EndStructure

Structure AMIARRAY
  ami.AmiVar[0]
EndStructure

Prototype.l pFunction(NumArgs.l, Array *ArgsTable.Amivar(1))
Structure FunDesc
  Function.l
  ArrayQty.b
  StringQty.b
  FloatQty.b
  DefaultQty.b
  *DefaultValues.FARRAY
EndStructure

Structure FunctionTag
  Name.STRING
  Descript.FunDesc
EndStructure

ProcedureDLL AttachProcess(Instanz.l)
  Global Dim FunctionTable.FunctionTag(#NumberofFunctions )
  Global Dim *myArgs.Amivar(0)
  Global *gpinterface.SiteInterface
 
  Global *erg.AmiVar
  Global Dim myInput.Amivar(0)
EndProcedure

ProcedureCDLL.l GetPluginInfo(*pinfo.Plugininfo)

  *pinfo\nStructSize = SizeOf(PluginInfo)
  *pinfo\nType = #PLUGIN_TYPE_AFL
  *pinfo\nVersion = #PLUGIN_VERSION
  *pinfo\nIDCode = 0
  *pinfo\szNname = #PLUGIN_NAME
  *pinfo\szVendor = #VENDOR_NAME
  *pinfo\nCertificate = 0
  *pinfo\nMinAmiVersion = 530000
  ProcedureReturn 1
EndProcedure

ProcedureCDLL.l Init()

  ProcedureReturn 1
EndProcedure

ProcedureCDLL.l Release()

  ProcedureReturn 1
EndProcedure

ProcedureCDLL.l SetSiteInterface(*pinterface.SiteInterface)
  *gpinterface = *pinterface
  ProcedureReturn 1
EndProcedure


ProcedureC.l BTS_Test(NumArgs.l, *pArgsTable.AmiVar)
   
  MessageRequester("NumArgs", Str(NumArgs.l))
  If NumArgs.l > 0
    ReDim *myArgs.Amivar(NumArgs.l - 1)
    For i=0 To NumArgs.l - 1
      *myArgs(i) = *pArgsTable + (i*SizeOf(AmiVar))
     
      MessageRequester("CurrentArg", Str(i))
      MessageRequester("type", Str(*myArgs(i)\type))
      MessageRequester("val", Str(*myArgs(i)\val))
    Next
  EndIf

;######################################

   MessageRequester("Test Amibroker Variables", "Read First Close Array values:") 
   strParam2.s = "close"
   *erg.Amivar = 0
   q_erg.q = 0
   q_erg.q = *gpinterface\GetVariable(@strParam2.s)
   *erg = @q_erg.q
   If *erg\type = #VAR_ARRAY
     For i=0 To 2
       MessageRequester("GetVariable close[" + Str(i) + "]", StrF(*erg\mArray\f[i]))
     Next
   EndIf


;#####################################
  MessageRequester("Test Amibroker Commands", "Try a version()")

  myinput.Amivar(0)\type = #VAR_NONE
  myinput.Amivar(0)\val = 0
 
  *erg.Amivar = 0
  q_erg.q = 0
  q_erg.q = *gpinterface\mCallFunction("version", 1, @myinput(0))
  *erg = @q_erg.q
 
  MessageRequester("Erg of version:", StrF(*erg\val))
 
  ProcedureReturn 1
EndProcedure



ProcedureCDLL.l GetFunctionTable(*ppFunctionTable)

  FunctionTable(0)\Name\s = "BTS_Test"
  FunctionTable(0)\Descript\Function = @BTS_Test()
  FunctionTable(0)\Descript\ArrayQty = 0
  FunctionTable(0)\Descript\StringQty = 0
  FunctionTable(0)\Descript\FloatQty = 0
  FunctionTable(0)\Descript\DefaultQty = 3
 
  *FunctionTable_DefaultValues.FARRAY = AllocateMemory(FunctionTable(0)\Descript\DefaultQty * 4)
  *FunctionTable_DefaultValues\f[0] = 1
  *FunctionTable_DefaultValues\f[1] = 2
  *FunctionTable_DefaultValues\f[2] = 5
 
  PokeL(@FunctionTable(0)\Descript\DefaultValues, *FunctionTable_DefaultValues)
  PokeL(*ppFunctionTable, @FunctionTable(0))
 
  ProcedureReturn #NumberofFunctions
EndProcedure



PS: Ich bin immer wieder beeindruckt wie schnell einem hier geholfen wird - dieses Forum ist wirklich das beste :-)

_________________
ActiveXInterfaceImporter und ActiveXLibrary


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye