Announcement

Collapse
No announcement yet.

Trouble converting from C to PB

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Trouble converting from C to PB


    I am trying to write a custom fitness function for the Discipulus genetic programming engine.
    They give an example of an API DLL interface written in C.
    I am trying to convert this to a PBWin DLL, however I do not have any experience with the C compiler or the Windows environment.
    There are 6 different calls made from the API to the PB dll. I have only been able to get the first one working.
    Can any one offer any suggestions to help get the rest to work?

    Code:
    unsigned int GetNrOfParameters()
    
    FUNCTION   GPgetNumParms ALIAS "GetNrOfParameters" () EXPORT AS LONG 
    'This is the only one that is working
    
    
    float CalculateTrainingFitness(FUNCTION_PTR pGeneticProgram, long Length)
    
    FUNCTION   GPcalcTF ALIAS "CalculateTrainingFitness" (   _   
                            BYVAL aGP AS DWORD PTR,_    
                            BYVAL Length AS LONG  ) EXPORT AS SINGLE  
    
    
    vvoid GetParameterInformation(unsigned int ParameterIndex,
        BSTR *ParameterName,
        BSTR *TypeInformation,
        BSTR *LowerBound,
        BSTR *UpperBound)
    
    SUB   GPgetParmInfo ALIAS "GetParameterInformation" ( _
                    ParmIdx AS LONG, _  
                    ParameterName AS ASCIIZ PTR, _
                    TypeInformation AS ASCIIZ PTR, _
                    LowerBound AS ASCIIZ PTR, _
                    Upperbound AS ASCIIZ PTR ) EXPORT 
    
    
    void SetParameterValue(unsigned int ParameterIndex, LPCTSTR Value)
    
    SUB   GPsetParmVal ALIAS "SetParameterValue" ( _
                    ParmIdx AS LONG, _
                    ParmVal AS ASCIIZ PTR ) EXPORT
    
    
    BSTR GetParameterValue(unsigned int ParameterIndex)
    
    FUNCTION   GPgetParmVal ALIAS "GetParameterValue" ( _
                    ParmIdx AS LONG) EXPORT AS STRING 
    
    void InitConstants(float *Constants, long NrOfConstants)
    
    SUB   GPinitConst ALIAS "InitConstants" ( _
                    pConstants AS DWORD, _  
                    NumOfConstants AS LONG ) EXPORT
    Thank you in advance for any help.
    Dennis


  • #2
    BSTR is equivalent to a PowerBASIC dynamic string (String data type). Try that.

    I noticed that you are also passing some parameters BYREF (default in PB), in C BYVAL is the default so those need to be changed as well.

    ------------------
    kgpsoftware.com - Downloads
    kgpsoftware.com - Development and Consulting

    [This message has been edited by Kev Peel (edited November 03, 2006).]
    kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

    Comment


    • #3
      Thanks Kev,

      The BYVAL got a little more stuff working!
      STRING and STRING PTR didn't make a difference.

      Thanks again,
      Dennis

      ------------------

      Comment


      • #4
        Thank you for your help. I am still having trouble converting the following function:

        Code:
        ////////////////////////////////////////////////////////////////////////////////////////
        // GetParameterInformation
        //
        // This procedure is used to provide parameter information to Discipulus(tm).
        // You don't need to change anything in here.
        ////////////////////////////////////////////////////////////////////////////////////////
        
        void GetParameterInformation(unsigned int ParameterIndex,
            BSTR *ParameterName,
            BSTR *TypeInformation,
            BSTR *LowerBound,
            BSTR *UpperBound)
        
        {
        	*ParameterName=((CString)Parameters[ParameterIndex].ParameterName).AllocSysString();
        	*TypeInformation=((CString)Parameters[ParameterIndex].TypeInformation).AllocSysString();
        	*LowerBound=((CString)Parameters[ParameterIndex].LowerBound).AllocSysString();
        	*UpperBound=((CString)Parameters[ParameterIndex].UpperBound).AllocSysString();
        }
        I think this means that my program is supposed to put the string information into the locations pointed to by the calling API. The program that I wrote is as follows:

        Code:
        '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
        SUB   GPgetParmInfo ALIAS "GetParameterInformation" ( _
                                	 BYVAL ParmIdx AS LONG, _  
                                	 BYVAL ParameterName AS STRING PTR, _
                                	 BYVAL TypeInformation AS STRING PTR, _
                                	 BYVAL LowerBound AS STRING PTR, _
                                	 BYVAL Upperbound AS STRING PTR) EXPORT                                                                                      
                                                                                 
            DIM PN$,TI$,LB$,UB$
            
             PN = "Parm 1"
             TI = "int"
             LB =  "3"
             UB = "99"     
        
             @ParameterName = PN
             @TypeInformation = TI
             @LowerBound =  LB
             @UpperBound = UB   
        
        MSGBOX("GetParameterInfo "+STR$(ParmIdx)+"."[email protected]+"."[email protected]+"."[email protected]+"."[email protected])
                                
        END SUB
        '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
        The calling API successfully calls my program and my program successfully puts the required text into the locations passed and then sends a msgbox verifying that the values have been successfully transferred. As soon as my program returns to the calling program it crashes. From this I assume that I have returned the information in a format that is not understood. I have tried converting the strings using UCODE$ before returining but this did not help.

        Can anyone offer any suggestions? I am at a complete loss as to what to try next!

        Thank you again,
        Dennis


        ------------------

        Comment


        • #5
          The problem could easily be in your calling procedure (not shown).

          When the string variables from which you get the pointers go out of scope, all your strings are invalid and a protection fault is the best you can hope for.

          Those strings need to remain in scope so their pointers remain valid... i.e, they must be STATIC or GLOBAL.

          And you are also talking about "returning to the calling program." Do you perhaps mean the calling procedure? None of this stuff is going to work across processes without some additional objects (e.g. global atoms).


          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Try using this:

            Code:
            SUB   GPgetParmInfo ALIAS "GetParameterInformation" ( _
                                    	 BYVAL ParmIdx AS DWORD, _  
                                    	 BYREF ParameterName AS DWORD, _
                                    	 BYREF TypeInformation AS DWORD, _
                                    	 BYREF LowerBound AS DWORD, _
                                    	 BYREF Upperbound AS DWORD) EXPORT                                                                                      
            
                DIM PN$,TI$,LB$,UB$
                
                PN = UCODE$("Parm 1")
                TI = UCODE$("int")
                LB = UCODE$("3")
                UB = UCODE$("99")
            
                ParameterName = SysAllocString(BYVAL STRPTR(PN))
                TypeInformation = SysAllocString(BYVAL STRPTR(TI))
                LowerBound = SysAllocString(BYVAL STRPTR(LB))
                UpperBound = SysAllocString(BYVAL STRPTR(UB))
            
            END SUB

            ------------------
            Website: http://com.it-berater.org
            SED Editor, TypeLib Browser, COM Wrappers.
            Forum: http://www.forum.it-berater.org
            Forum: http://www.jose.it-berater.org/smfforum/index.php

            Comment


            • #7
              >ParameterName = SysAllocString(BYVAL STRPTR(PN))

              Dont forget, you are now responsible for DE-allocating those strings!
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                I don't know, since I haven't seen the documentation. Usually, the caller
                is responsible to deallocate them, since only him knows when no longer
                needs them.


                ------------------
                Website: http://com.it-berater.org
                SED Editor, TypeLib Browser, COM Wrappers.
                Forum: http://www.forum.it-berater.org



                [This message has been edited by José Roca (edited November 06, 2006).]
                Forum: http://www.jose.it-berater.org/smfforum/index.php

                Comment


                • #9
                  Thank you very much for your suggestions!

                  I am afraid that I'm such a newbie with window's stuff that I can't begin to understand what you are suggesting.
                  I tried what Jose suggested but it also did not work.
                  I have been able to find out that the example was written using VS 6.0 .NET.
                  I don't know if that makes this any easier or not but I'll keep working on it.

                  Thank you all again,
                  Dennis


                  ------------------

                  Comment


                  • #10
                    What would really help?

                    Post the complete code you are using to test, which code fails. (The BASIC code you wrote, not the C stuff).

                    You should have source code for your DLL, and source code for the EXE program which uses your DLL.

                    What you have posted so far just doesn't cover everything. For all we know, you failed to return %TRUE in Libmain on DLL_PROCESS_ATTACH. That would explain "not working" very quickly. (Would only pertain if you are calling dynamically, but we don't know if you are doing that or not, do we?)

                    MCM


                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      Below you will find my complete code for the dll interface to the Discipulus GP program.
                      I do not have any source code for Discipulus, I just have the example of how to interface to it.

                      I believe that the simple functions are all working. That is the ones that only return a long.

                      The one I am trying to get to work now is "GetParameterInformation".

                      I have not started on InitConstants, SetParameterValue, GetParameterValue, or CalculateTrainingFitness.

                      Thank you very much for your thoughts!
                      DM

                      Code:
                      		
                      '  =============================================================================
                      '  COMPILER DIRECTIVES
                      '  =============================================================================
                      ' 
                      #DEBUG ERROR ON   
                      #COMPILE DLL "C:\DASTEC~1\GPD2.DLL" ' For Discipulus  
                      #DIM ALL
                                                                              
                      #INCLUDE "WIN32API.INC"         '  Everything in WIN32API isn't needed in Template,
                      
                      #IF NOT %DEF(%WINAPI)
                         %WINAPI = 1     
                         '  To avoid redundant code, make sure %CCWIN 
                         '  is always defined for PB/DLL.
                         #IF NOT %DEF(%PB_CC32)
                             #IF NOT %DEF(%CCWIN)
                                 %CCWIN = 1
                             #ENDIF
                         #ENDIF
                      
                         %DLL_PROCESS_DETACH      = 0
                         %DLL_PROCESS_ATTACH      = 1
                         %DLL_THREAD_ATTACH       = 2
                         %DLL_THREAD_DETACH       = 3
                      #ENDIF   
                                     
                      
                      
                      'xConfirm  4000                                         ' Show COMPILE Confirmation
                      'xErrors   6000                                         ' Show Errors
                      'xCompress                                              ' Compress file 
                      
                      $DLL_VERSION = "1.0.1"        '  Holds the Current DLL version Number
                                                    
                      GLOBAL gNumOfTimes AS DWORD   '  Counts # of times LibMain is called - Debug
                       
                      DECLARE SUB   GPinitParms ()	' Parameter Info
                      
                       
                      '  =============================================================================
                      '      Shell File Open - Send Message process to create a popup text messages
                      '  ============================================================================= 
                      SUB SendMsgBox( TextStringMsg AS STRING )
                         DIM FilNum AS LONG
                         
                         FilNum = FREEFILE                        '  Log File DOS Handle # 
                         OPEN "C:\ErrMsg.Txt" FOR OUTPUT AS #FilNum '  Open OR Create a File  
                            
                         PRINT #FilNum, STRING$(30, "=")
                         PRINT #FilNum, " DLL Message: ";DATE$;" ";TIME$
                         PRINT #FilNum, TextStringMsg              
                         PRINT #FilNum, STRING$(30, "=")
                         
                         CLOSE #FilNum                         '  Close this File
                      
                         FilNum = SHELL("NotePad.EXE C:\ErrMsg.Txt", 1)
                      
                      END SUB
                      '  =============================================================================
                      '      Shell File Open - Send Message process to create a popup text messages
                      '  ============================================================================= 
                                
                       
                      '  Main DLL Module Function is called when the DLL is attached and when it 
                      
                      FUNCTION LIBMAIN(BYVAL hInstance AS DWORD,_
                                       BYVAL Reason    AS LONG,_
                                       BYVAL Reserved  AS LONG) AS LONG
                         
                         DIM Msg$                                              '  Variable for Debug - Debug
                         
                         INCR gNumOfTimes                                      '  Counts LibMain calls - Debug
                         
                         SELECT CASE Reason
                            CASE %DLL_PROCESS_ATTACH       
                      '        MSGBOX "%DLL_PROCESS_ATTACH"                   '  Dialog Popup if needed - Debug
                      	     GPinitParms( )	' Initialize Discipulus
                               LIBMAIN = 1
                               EXIT FUNCTION                                   '  LIBMAIN
                      
                            CASE %DLL_PROCESS_DETACH
                      '         MSGBOX "%DLL_PROCESS_DETACH"                   '  Dialog Popup if needed - Debug
                               EXIT FUNCTION                                   '  LIBMAIN
                         
                            CASE %DLL_THREAD_ATTACH
                      '         MSGBOX "%DLL_THREAD_ATTACH"                    '  Dialog Popup if needed - Debug         
                               EXIT FUNCTION                                   '  LIBMAIN
                         
                            CASE %DLL_THREAD_DETACH                                        
                      '         MSGBOX "%DLL_THREAD_DETACH"                    '  Dialog Popup if needed - Debug         
                               EXIT FUNCTION                                   '  LIBMAIN
                            
                            END SELECT  '  CASE Reason
                         
                         ' If you get here, you are in serious trouble
                         CALL SendMsgBox("Windows Error in Main DLL - Reboot Windows" + "DM-Main - Missed CASE >=")
                         
                         '   A Serious Failure has Occured!
                         LIBMAIN = 0            
                         
                      END FUNCTION   '  LIBMAIN
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                      
                      GLOBAL pGP AS DWORD
                      GLOBAL Pidx AS LONG
                      
                      
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      '	Main Discipulus Function
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      FUNCTION GPidentify ALIAS "Identify" () EXPORT AS LONG ' Version 
                       
                      MSGBOX("Identify")
                         
                      		FUNCTION = 2
                               
                               
                      END FUNCTION
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                         
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      FUNCTION   GPcalcTF ALIAS "CalculateTrainingFitness" (        _                       	' Calculate Fitness Routine 
                                              BYVAL aGP AS DWORD PTR,_         			                    ' Genetic Program Pointer
                                              BYVAL Length AS LONG  ) EXPORT AS SINGLE 	                    ' Fitness Value ( The lower the value, the better the program)  
                                                                  
                              pGP = aGP 
                              
                      MSGBOX("CalcTrainFitness "+STR$(length)+"  "+STR$(aGP))
                      
                              '////////////////////////////////////////////////////////////////////////////////////////
                              '// CalculateTrainingFitness
                              '// 
                              '// Calculates the fitness OF an individual having direct ACCESS TO the genetic
                              '// program itself, allowing you TO DO WITH it whatever you want.
                              '//
                              '// Parameters:
                              '//		pGeneticProgram		- POINTER TO the genetic program. This IS how you CALL it:
                              '//			(*pGeneticProgram) (Inputs, pOutputs)
                              '//
                              '//			Inputs IS an ARRAY OF floats used AS the INPUT OF the program. The SIZE OF 
                              '//			this ARRAY must be equal TO the number OF inputs FOR the genetic program, 
                              '//			SET IN varable NrOfInputs.
                              '//
                              '//			pOutputs IS a POINTER TO an ARRAY that contains the outputs OF the
                              '//			program after the FUNCTION has been called. The SIZE OF the ARRAY will be 
                              '//			NrOfOutputs.
                              '//
                              '// RETURN Value:
                              '//		The fitness value OF the program. The lower the fitness value, the better
                              '//		the program.
                              '////////////////////////////////////////////////////////////////////////////////////////
                              
                              'float CalculateTrainingFitness(FUNCTION_PTR pGeneticProgram, LONG Length)
                          
                          '	// Init inputs. Note: Inputs[1] TO Inputs[3] are never
                          '	// changed, so they are CONSTANTS FOR the GP program
                          	DIM Inputs(4) AS SINGLE 
                          	    Inputs(0)=0 : Inputs(1)=0 : Inputs(2)=0 : Inputs(3)=.5 : Inputs(4)=1
                          
                          '	// POINTER TO evolved program OUTPUT
                          	DIM Outputs(8) AS SINGLE PTR
                          
                          	DIM ER!, ErrorSum!, NrOfFitnessCases&, x!
                          
                          	FOR  x=-2 TO 1.999 STEP 0.2        ' // The stepsize here is 0.2    	
                          		'// SET the INPUT
                          		Inputs(0)=x
                          
                          		'// CALL evolved program
                          		'(*pGeneticProgram)(Inputs,Outputs);
                          
                          		'// Calculate ERROR
                          		ER= ABS(@Outputs(0)-(x*x*x+x*x+x))  ' // We want to evolve x^3 + x^2 + x...    		
                          		'// Square the ERROR
                          		ER=ER*ER
                             		'// Sum up errors
                          		ErrorSum=ErrorSum+ER
                             		'// Count the number OF fitness cases we tested
                          		NrOfFitnessCases=NrOfFitnessCases+1
                              NEXT x
                                  
                          	'// RETURN average squared ERROR
                          	FUNCTION = ErrorSum/NrOfFitnessCases
                          
                                           
                      END FUNCTION
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              
                              
                              
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      FUNCTION   GPcalcVF ALIAS "CalculateValidationFitness" (        _                       	' Calculate Fitness Routine 
                                              BYVAL aGP AS DWORD PTR ,_         			' Genetic Program Pointer
                                              BYVAL Length AS LONG  ) EXPORT AS SINGLE 	' Fitness Value ( The lower the value, the better the program)
                                                                   
                              pGP = aGP 
                              
                      MSGBOX("CalcValidateFitness "+STR$(length)+"  "+STR$(aGP))
                                       
                          	DIM Inputs(4) AS SINGLE 
                          	    Inputs(0)=0 : Inputs(1)=0 : Inputs(2)=0 : Inputs(3)=.5 : Inputs(4)=1
                          
                          '	// POINTER TO evolved program OUTPUT
                          	DIM Outputs(8) AS SINGLE PTR
                          
                          	DIM ER!, ErrorSum!, NrOfFitnessCases&, x!
                          
                          	FOR  x=-2 TO 1.999 STEP 0.3        '// FOR validation we use a different stepsize (0.3).
                          								        '// Everything ELSE remains the same.
                          								            								        
                          		'// SET the INPUT
                          		Inputs(0)=x
                          
                          		'// CALL evolved program
                          		'(*pGeneticProgram)(Inputs,Outputs);
                          
                          		'// Calculate ERROR
                          		ER= ABS(@Outputs(0)-(x*x*x+x*x+x))  ' // We want to evolve x^3 + x^2 + x...    		
                          		'// Square the ERROR
                          		ER=ER*ER    
                          		'// Sum up errors
                          		ErrorSum=ErrorSum+ER
                             		'// Count the number OF fitness cases we tested
                          		NrOfFitnessCases=NrOfFitnessCases+1
                              NEXT x
                           
                          	'// RETURN average squared ERROR
                          	FUNCTION = ErrorSum/NrOfFitnessCases
                               
                      END FUNCTION
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                         
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      FUNCTION   GPgetNumInp ALIAS "GetNrOfInputs" () EXPORT AS LONG 	' Fitness Value ( The lower the value, the better the program)
                                                   
                      MSGBOX("GetNrOfInputs")
                                           
                          FUNCTION = 4  
                          
                      END FUNCTION
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                         
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      FUNCTION   GPgetNumOut ALIAS "GetNrOfOutputs" () EXPORT AS LONG 	' Fitness Value ( The lower the value, the better the program)
                                                  
                      MSGBOX("GetNrOfOutputs")
                                           
                          FUNCTION = 1  
                          
                      END FUNCTION
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      FUNCTION   GPgetNumParms ALIAS "GetNrOfParameters" () EXPORT AS LONG 	' Fitness Value ( The lower the value, the better the program)
                                           
                                           
                      	DIM Num AS LONG
                      	Num = 1
                      		        
                      MSGBOX("GetNrOfParameters "+STR$(Num))
                                           
                          FUNCTION = Num
                          
                      END FUNCTION
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                      
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      FUNCTION   GPgetParmVal ALIAS "GetParameterValue" ( _
                                              BYVAL ParmIdx AS LONG) EXPORT AS STRING  	' Parameter Value
                                                                        
                      MSGBOX("GetParmVal "+STR$(ParmIdx))
                                                 
                      END FUNCTION
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                      
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      SUB   GPsetParmVal ALIAS "SetParameterValue" ( _
                                              	 BYVAL ParmIdx AS LONG, _
                                                   BYVAL ParmVal AS STRING PTR) EXPORT 	' Parameter Value                                         
                                      
                      MSGBOX("SetParmVal "+STR$(ParmIdx))'+"  "+ParmVal)
                          
                      END SUB
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                      
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      SUB   GPgetParmInfo ALIAS "GetParameterInformation" ( _
                                              	 BYVAL ParmIdx AS DWORD, _  
                                              	 BYREF ParameterName AS DWORD, _
                                              	 BYREF TypeInformation AS DWORD, _
                                              	 BYREF LowerBound AS DWORD, _
                                              	 BYREF Upperbound AS DWORD) EXPORT
                                                                                                            
                                                                                        
                      MSGBOX("GetParameterInfo "+STR$(ParmIdx)+"."+STR$(ParameterName)+"."+STR$(TypeInformation)+"."+STR$(LowerBound)+"."+STR$(Upperbound))
                              
                          DIM PN$,TI$,LB$,UB$
                                  
                          PN = UCODE$("Parm 1")
                          TI = UCODE$("int")
                          LB = UCODE$("3")
                          UB = UCODE$("99")     
                          
                          ParameterName = SysAllocString(BYVAL STRPTR(PN))
                          TypeInformation = SysAllocString(BYVAL STRPTR(TI))
                          LowerBound = SysAllocString(BYVAL STRPTR(LB))
                          UpperBound = SysAllocString(BYVAL STRPTR(UB))
                      
                      
                      MSGBOX("GetParameterInfo - Return:"+STR$(ParmIdx))
                                           
                          
                      END SUB
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      SUB   GPinitConst ALIAS "InitConstants" ( _
                                              	 BYVAL pConstants AS DWORD, _  
                                              	 BYVAL NumOfConstants AS LONG ) EXPORT 	' Parameter Info
                                           
                                           
                              
                      MSGBOX("InitConst "+STR$(NumOfConstants)+"  "+STR$(pConstants))
                                           
                      END SUB
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      
                      
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
                      SUB   GPinitParms ( ) 	' Parameter Info
                                           
                              
                              
                      'MSGBOX("InitParms ")        
                      
                          
                      END SUB
                      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤


                      ------------------

                      Comment


                      • #12
                        I'm not a 'C' programmer but doesn''t...
                        Code:
                        void GetParameterInformation(unsigned int ParameterIndex, 
                              BSTR *ParameterName,
                              BSTR *TypeInformation,
                              BSTR *LowerBound,
                              BSTR *UpperBound)
                        ... say that what is passed as params 2-5 is a POINTER to a BSTR?

                        If so then then I think those parameters should be DECLAREd as "BYREF STRING"

                        Then ..
                        ParameterName = "abc"
                        ... would handle the allocation.

                        But that's exactly the same as the gpGetParmInfo function which you state IS working...because "BYVAL x AS STRING PTR" is the same as "BYREF X AS STRING"

                        But for that function you state that you have problems "As soon as my program returns to the calling program it crashes." ("crash" = Some kind of protection fault? Bad Data? )

                        That does NOT mean your problem is in the GpGetParamInfo function. Memory corruption errors rarely show themselves "at the exact time the statement is executed"

                        You also never answered the challenge of defining "calling program." If your function is located in a DLL loaded by your EXE, there is no other "program" involved. Is something else going on here we need to know about?

                        If GpGetParmInfo is working... then GetParameterInformation should work exactly the same way, and your problem is elsewhere.

                        MCM

                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment


                        • #13

                          José' translation is the closest, the strings must be dynamically allocated as shown in the
                          posted C++ code (it is C++, not standard C). My only guess at this point would be to check
                          the calling convention and check an existing copy of the DLL plugin to compare exports.

                          You can compare exported functions by using the Dependency Walker tool, which can be
                          downloaded free from the following location:

                          http://www.dependencywalker.com/

                          ------------------
                          kgpsoftware.com - Downloads
                          kgpsoftware.com - Development and Consulting
                          kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                          Comment


                          • #14
                            >strings must be dynamically allocated

                            "ParameterInfo ="12345"" is dynamically allocating the string.

                            And it shouldn't go out of scope, since the string was passed and the compiler will assume the deallocation is handled by the calling routine.

                            (At least I'd try it that way.) (But then I'd probably try using SysAllocString, too)

                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15

                              In the C++ code, you are passed several pointer variables (DWORDS), which
                              you must assign a string handle with SysAllocString. My original observation
                              about using BYREF STRING was not quite correct, it would have to be a DWORD
                              (or LONG for that matter). Simply assigning a value to the provided buffer
                              would not work because:


                              1) The parameter value is NULL, which must be set to an allocated OLE string (probably UNICODE).
                              2) If PB allocated a string on the stack, it would be erased after the call.


                              We can only assume that the caller handles all deallocations.

                              ------------------
                              kgpsoftware.com - Downloads
                              kgpsoftware.com - Development and Consulting
                              kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                              Comment


                              • #16
                                Thank you for all this!

                                I am in the process of getting a working dll example from the vendor.

                                Kev, would what you are suggesting make any changes to Jose's suggested code?

                                Thank you again,
                                Dennis


                                ------------------

                                Comment


                                • #17
                                  Maybe you have to use CDECL. If I'm not wrong, C uses CDECL unless
                                  another call type is specified.

                                  ------------------
                                  Website: http://com.it-berater.org
                                  SED Editor, TypeLib Browser, COM Wrappers.
                                  Forum: http://www.forum.it-berater.org
                                  Forum: http://www.jose.it-berater.org/smfforum/index.php

                                  Comment


                                  • #18
                                    Dennis,

                                    No, that is how I would have translated it. My moneys on the calling convention being incorrect

                                    ------------------
                                    kgpsoftware.com - Downloads
                                    kgpsoftware.com - Development and Consulting
                                    kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                                    Comment


                                    • #19
                                      Bingo - Jose hit it! Back making progress again!
                                      I had tried CDECL but not with everything else in place.

                                      Thank you very much!
                                      Dennis


                                      ------------------

                                      Comment


                                      • #20
                                        Then, with GPgetParmVal you have to do the same:
                                        Code:
                                        FUNCTION GPgetParmVal CDECL ALIAS "GetParameterValue" ( _
                                                              BYVAL ParmIdx AS LONG) EXPORT AS DWORD
                                        
                                           DIM retval AS STRING
                                           retval = UCODE$("some value")
                                           FUNCTION = SysAllocString(BYVAL STRPTR(retval))
                                        
                                        END FUNCTION

                                        ------------------
                                        Website: http://com.it-berater.org
                                        SED Editor, TypeLib Browser, COM Wrappers.
                                        Forum: http://www.forum.it-berater.org

                                        [This message has been edited by José Roca (edited November 07, 2006).]
                                        Forum: http://www.jose.it-berater.org/smfforum/index.php

                                        Comment

                                        Working...
                                        X