Amibroker AFL - Plugin

Just starting out? Need help? Post your questions and find answers here.
VoSs2o0o
User
User
Posts: 24
Joined: Fri Aug 06, 2010 11:46 pm

Amibroker AFL - Plugin

Post by VoSs2o0o »

Hello,

i have tried to program an Amibroker plugin (http://www.amibroker.com). The Plugin works so far,
but the SiteInterface don't work. This is the original c/c++ code of this Structure:

Code: Select all

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
};
This is my Interpretation:

Code: Select all

Structure SiteInterface
  nStructSize.l
  *GetArraySize.pGetArraySize
  *GetStockArray.pGetStockArray
  *GetVariable.pGetVariable
  *SetVariable.pSetVariable
  *mCallFunction.pCallFunction
  *AllocArrayResult.pAllocArrayResult
  *Alloc.pAlloc
  *Free.pFree
  *GetDateTimeArray.pGetDateTimeArray
EndStructure
but i get an Memory Error every time. Also i get nonsense data an no pointer as return value.
for Example when i try to get a Variable with GetVariable

Here the Code which generates a AFL-Command "BTS_Test". The Plugin is generally working except the "Siteinterface"
Something could be better written in this code, but this is only a Test how this can be done in PB.

Code: Select all

#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
I hope sombody can help to solve the "siteinterface" - Problem.
You can get the Amibroker "ADK" from the download-page of Amibroker.com.
In this ADK are also some c/c++ sources an a How To for Amibroker Plugins.
VoSs2o0o
User
User
Posts: 24
Joined: Fri Aug 06, 2010 11:46 pm

Re: Amibroker AFL - Plugin

Post by VoSs2o0o »

I have found the solution, and will post a correct code in the next days....
VoSs2o0o
User
User
Posts: 24
Joined: Fri Aug 06, 2010 11:46 pm

Re: Amibroker AFL - Plugin

Post by VoSs2o0o »

So here is a fully working example of an Amibroker AFL Plugin.

Code: Select all


#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


User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Amibroker AFL - Plugin

Post by luis »

I use Amibroker but right now I have zero time to look at this, only wanted to thank you for sharing it.

:)
"Have you tried turning it off and on again ?"
A little PureBasic review
Post Reply