How to call function from .dll library?

General Help regarding HMG, Compilation, Linking, Samples

Moderator: Rathinagiri

KDJ
Posts: 243
Joined: Mon Sep 05, 2016 3:04 am
Location: Poland

Re: How to call function from .dll library?

Post by KDJ »

Marek

Podaj typy parametrów przekazywanych do funkcji DataSend oraz typ zwracanej wartości.
Znajdziesz to w deklaracji funkcji.
Rozumiem, że jednym z parametrów jest struktura Scale.
User avatar
mol
Posts: 3718
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: How to call function from .dll library?

Post by mol »

Cześć Krzysztof, dzięki za zainteresowanie!
Podsyłam fragment dokumentacji.
Do wysyłania towarów na wagę poprzez parametry służy funkcja [ItemsSend[/b]
Możnaby napisać fragment w C, który będzie przekazywał właściwe parametry, spróbuję to jutro zrobić.
Niemniej cienki jestem po prostu z C :)
SEND ITEMS THROUGH PARAMETERS
It is not necessary to create a file, because all the articles and scales are inserted by code.
string WINAPI ItemsSend (Scale * myScales, int numScales,
Item * myItems, int numItems
int showWindow, int closeTime)
This function accepts as parameters all the articles to be sent and all data of the scales.
When the function is called, it sends all the articles to the scales. The function returns a
string which shows the result of the communication process when it completes the
process.
2.2.1 ItemsSend Function
This function allows sending a set of articles to the scales.
string WINAPI ItemsSend (Scale * myScales, int numScales,
Item * myItems, int numItems,
int showWindow, int closeTime)
Parameters:
1) myScales, Pointer to an array of “Scale” type structures with all the scales.
2) numScales, The total number of scales that the scales’ array has.
3) myItems, Pointer to an array of “Item” type structures with all the articles to be
sent to the scales.
4) numItems, The total number of articles that the articles’ array has.
5) showWindow, Show communication window.
Values: 0 -> Don’t show
1 -> Show
6) closeTime, Number of seconds that the window will be show alter
communication.
Values: -1 -> Close manually
X -> Number of seconds to close automatically
alter that the communication has finalized.
Result: The function will return a string with the following values:
1) If the communication with all the Scales is correct:
Result = “OK”
2) If the communication in any of the scales is not correct: It will return the
ipAddress of the scales with erroneous communication, separated with point &
comma (“;”)
Result = “192.168.1.2;192.168.1.3”
3) If the dll (commL.dll), which is necessary for the communication, has not been
added to the project, it will return a string “No commL.dll”.
Result = “No commL.dll”
Note: The register generated by ItemsSend function to send each Item is:
China -> L2_C
Rest -> AG ( 102E scale version or later is required )V 1.0.0.4_EN 7
SCALE STRUCTURE
This structure defines the scale with which the communication is stablished.
typedef struct _Scale
{
int masterAddress;
LPWSTR ipAddress;
int txPort;
int rxPort;
LPWSTR model;
LPWSTR display;
LPWSTR section;
int group;
LPWSTR logsPath;
}Scale;
Where:
- masterAddress: Logic address of the scale (Master Address). The registers will be
modified to assign this logic address.
Data type: int -> Integer without sign (4 bytes).
- ipAddress: IP address of the scale.
Data type: LPWSTR -> Wide character string.
- txPort: Port of the scale where we must connect for sending data to the scale.
Data type: int -> Integer without sign (4 bytes). (Is not in used)
- rxPort: Port of the scale where we must connect for receiving data to the scale.
Data type: int -> Integer without sign (4 bytes).
- model: Define the scale model.
Values:
500RANGE -> Is a Gamma 500 scale.
LSERIES -> Is a L series scale.
Data type: LPWSTR -> Wide character string.
- display: Type of scale display. (Is not in used)
Values:
ALPHANUMERIC -> Scale with alphanumeric display
GRAPHIC -> Scale with graphic display
Data type: LPWSTR -> Wide character string.
- section: Sections associated to the scale. If there are multiple sections they must be
separated with commas (“,”).(Is not in used)
Data type: LPWSTR -> Wide character string.
- group: Group of the scale. The registers will be modified to assign this Group number.
Data type: int -> Integer without sign (4 bytes).
- logsPath: Path for the logs file, this file have all the registers of communication. If it is
empty the communication logs will not be recorded. (It is not used)
Data type: LPWSTR -> Wide character string.V 1.0.0.4_EN 8
ITEM STRUCTURE
This is the structure to define the article data to be sent to the scale.
typedef struct _Item
{
int code;
int directKey;
double price;
LPWSTR name;
int type;
int section;
LPWSTR expiryDate;
int alterPrice;
int number;
int priceFactor;
LPWSTR textG;
}Item;
Where:
- code : Article Identification code (maxValue = 999999).
Data type: int -> Integer without sign (4 bytes).
- directKey: Direct key associated to the article (maxValue = 999).
Data type: int -> Integer without sign (4 bytes).
- price: Article price (maxValue= 9999,99). Data type: double(8 bytes)
- name: Article name (maxLength=36 bytes, for China).
Data type: LPWSTR -> Wide character string.
- type: Type of article. Data type: int -> Integer without sign (4 bytes).
0-> Weighed
1-> Non Weighed
- section: Article section. Data type: int -> Integer without sign (4 bytes).
- expiryDate: Best before date (format: dd/MM/yyyy).
Data type:LPCSTR -> Character string constant.
- alterPrice: Allows to modify the item price. Data type: int->Integer without sign (4
bytes). 0 -> Allows to modify the price.
1 -> Don’t allow to modify the price.
- number: PLUNumber, 9 digits number to be printed in the label
(maxValue=999999999)
Data type: int -> Integer without sign (4 bytes).
- priceFactor: Determines the weight base of the price.
Data type: int -> Integer without sign (4 bytes).
0 -> Yuan/kg
1 -> Yuan/100g
2 -> Yuan/500g
- textG: Item G text. (maxLegth = 1024 bytes). Data type: Byte array. (It is not used
[/
User avatar
mol
Posts: 3718
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: How to call function from .dll library?

Post by mol »

My idea is to write function in C which calls ItemsSend funtion from .dll
But, I need to transfer to C function two 2-dimensional arrays.
I don't know how to manipulate nested array passed to function in C api.

I can get master array by aScales= hb_param(1, HB_IT_ARRAY), is it correct?

but:
aScale = aScales[0];
is it correct?
Has anybody sample of C code?
Last edited by mol on Sat Jun 17, 2017 2:15 pm, edited 1 time in total.
User avatar
mol
Posts: 3718
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: How to call function from .dll library?

Post by mol »

apais wrote: Fri Jun 16, 2017 4:46 pm A C structure is a continuous and positional list of characters, while a harbour array is a pointer to a dynamic non-continuous set of chars.
In your case the representation of the structure would be something similar to: 00192.168.20.18130013000500RANGEALPHANUMERICSection0
But I'm sure a C profesional can tell you the exact translation of that. You have to know how many digits an int is and the exact length of the structure.
Also how they represent a null char for the last parameter

HTH
Angel
Strings have variable length, so, how should they be terminated? by chr(0) (as I remember chr(0) is string terminator in C)
KDJ
Posts: 243
Joined: Mon Sep 05, 2016 3:04 am
Location: Poland

Re: How to call function from .dll library?

Post by KDJ »

Marek

Try this. Compiled without errors, but I have no possibility to test.

Code: Select all

#include "hmg.ch"

FUNCTION Main()
  LOCAL aScale      := {}
  LOCAL aItem       := {}
  LOCAL lShowWindow := .T.
  LOCAL nCloseTime  := -1

  aAdd(aScale, { 0,              ; //masterAddress
                 "192.168.1.2",  ; //ipAddress
                 3001,           ; //txPort
                 3000,           ; //rxPort
                 "500RANGE",     ; //model
                 "ALPHANUMERIC", ; //display
                 "Section",      ; //section
                 0,              ; //group
			           ""              ; //logsPath
               })
  aAdd(aScale, { 0,              ; //masterAddress
                 "192.168.1.3",  ; //ipAddress
                 3001,           ; //txPort
                 3000,           ; //rxPort
                 "500RANGE",     ; //model
                 "ALPHANUMERIC", ; //display
                 "Section",      ; //section
                 0,              ; //group
			           ""              ; //logsPath
               })

  aAdd(aItem, { 1,            ; //code
                1,            ; //directKey
                24.51,        ; //price
                "Name1",      ; //name
                0,            ; //type
                9,            ; //section
                "18/07/2017", ; //expiryDate
                0,            ; //alterPrice
                999999999,    ; //number
			          0,            ; //priceFactor
			          ""            ; //textG
              })
  aAdd(aItem, { 2,            ; //code
                1,            ; //directKey
                19.37,        ; //price
                "Name2",      ; //name
                0,            ; //type
                9,            ; //section
                "18/10/2017", ; //expiryDate
                0,            ; //alterPrice
                999999998,    ; //number
			          0,            ; //priceFactor
			          ""            ; //textG
              })

  MsgBox(Dibalscop_ItemsSend(aScale, aItem, lShowWindow, nCloseTime))

RETURN NIL


#pragma BEGINDUMP

#include "SET_COMPILE_HMG_UNICODE.ch"
#include "HMG_UNICODE.h"

#include <windows.h>
#include "hbapi.h"
#include "hbapiitm.h"

typedef struct _SCALE
{
  INT    masterAddress;
  LPWSTR ipAddress;
  INT    txPort;
  INT    rxPort;
  LPWSTR model;
  LPWSTR display;
  LPWSTR section;
  INT    group;
  LPWSTR logsPath;
} SCALE;

typedef struct _ITEM
{
  INT    code;
  INT    directKey;
  DOUBLE price;
  LPWSTR name;
  INT    type;
  INT    section;
  LPWSTR expiryDate;
  INT    alterPrice;
  INT    number;
  INT    priceFactor;
  LPWSTR textG;
} ITEM;


        //Dibalscop_ItemsSend(aScale, aItem, lShowWindow, nCloseTime)
HB_FUNC ( DIBALSCOP_ITEMSSEND )
{
  LPWSTR WINAPI (*pItemsSend)(SCALE * myScales, INT numScales, ITEM * myItems, INT numItems, INT showWindow, INT closeTime);

  HMODULE  hLib      = LoadLibraryA("Dibalscop.dll");
  PHB_ITEM pArray    = hb_itemNew(NULL);
  PHB_ITEM pSubArray = hb_itemNew(NULL);
  HB_SIZE  nScales;
  HB_SIZE  nItems;
  UINT     n;

  if (hLib)
  {
    pItemsSend = (LPWSTR WINAPI (*)(SCALE *, INT, ITEM *, INT, INT, INT)) GetProcAddress(hLib, "ItemsSend");

    if (pItemsSend)
    {
      pArray  = hb_param(1, HB_IT_ARRAY);
      nScales = hb_arrayLen(pArray);

      SCALE sc[nScales];

      for (n = 0; n < nScales; ++n)
      {
        hb_arrayGet(pArray, n+1, pSubArray);
        
        sc[n].masterAddress = (INT)    hb_arrayGetNI   (pSubArray, 1);
        sc[n].ipAddress     = (LPWSTR) HMG_arrayGetCPtr(pSubArray, 2);
        sc[n].txPort        = (INT)    hb_arrayGetNI   (pSubArray, 3);
        sc[n].rxPort        = (INT)    hb_arrayGetNI   (pSubArray, 4);
        sc[n].model         = (LPWSTR) HMG_arrayGetCPtr(pSubArray, 5);
        sc[n].display       = (LPWSTR) HMG_arrayGetCPtr(pSubArray, 6);
        sc[n].section       = (LPWSTR) HMG_arrayGetCPtr(pSubArray, 7);
        sc[n].group         = (INT)    hb_arrayGetNI   (pSubArray, 8);
        sc[n].logsPath      = (LPWSTR) HMG_arrayGetCPtr(pSubArray, 9);
      }

      pArray = hb_param(2, HB_IT_ARRAY);
      nItems = hb_arrayLen(pArray);

      ITEM it[nItems];

      for (n = 0; n < nItems; ++n)
      {
        hb_arrayGet(pArray, n+1, pSubArray);
        
        it[n].code        = (INT)    hb_arrayGetNI   (pSubArray,  1);
        it[n].directKey   = (INT)    HMG_arrayGetCPtr(pSubArray,  2);
        it[n].price       = (DOUBLE) hb_arrayGetND   (pSubArray,  3);
        it[n].name        = (LPWSTR) hb_arrayGetNI   (pSubArray,  4);
        it[n].type        = (INT)    HMG_arrayGetCPtr(pSubArray,  5);
        it[n].section     = (INT)    HMG_arrayGetCPtr(pSubArray,  6);
        it[n].expiryDate  = (LPWSTR) HMG_arrayGetCPtr(pSubArray,  7);
        it[n].alterPrice  = (INT)    hb_arrayGetNI   (pSubArray,  8);
        it[n].number      = (INT)    HMG_arrayGetCPtr(pSubArray,  9);
        it[n].priceFactor = (INT)    HMG_arrayGetCPtr(pSubArray, 10);
        it[n].textG       = (LPWSTR) HMG_arrayGetCPtr(pSubArray, 11);
      }

      HMG_retc(pItemsSend(sc, nScales, it, nItems, hb_parl(3), hb_parni(4)));
    }
    else
    {
      HMG_retc(L"No ItemsSend function");
    }

    FreeLibrary(hLib);
  }
  else
  {
    HMG_retc(L"No Dibalscop.dll");
  }
}

#pragma ENDDUMP


/*
SEND ITEMS THROUGH PARAMETERS
It is not necessary to create a file, because all the articles and scales are inserted by code.
string WINAPI ItemsSend (Scale * myScales, int numScales,
Item * myItems, int numItems
int showWindow, int closeTime)
This function accepts as parameters all the articles to be sent and all data of the scales.
When the function is called, it sends all the articles to the scales. The function returns a
string which shows the result of the communication process when it completes the
process.

2.2.1 ItemsSend Function
This function allows sending a set of articles to the scales.
string WINAPI ItemsSend (Scale * myScales, int numScales,
Item * myItems, int numItems,
int showWindow, int closeTime)

Parameters:
1) myScales, Pointer to an array of “Scale” type structures with all the scales.
2) numScales, The total number of scales that the scales’ array has.
3) myItems, Pointer to an array of “Item” type structures with all the articles to be
sent to the scales.
4) numItems, The total number of articles that the articles’ array has.
5) showWindow, Show communication window.
Values: 0 -> Don’t show
1 -> Show
6) closeTime, Number of seconds that the window will be show alter
communication.
Values: -1 -> Close manually
X -> Number of seconds to close automatically
alter that the communication has finalized.

Result: The function will return a string with the following values:
1) If the communication with all the Scales is correct:
Result = “OK”
2) If the communication in any of the scales is not correct: It will return the
ipAddress of the scales with erroneous communication, separated with point &
comma (“;”)
Result = “192.168.1.2;192.168.1.3”
3) If the dll (commL.dll), which is necessary for the communication, has not been
added to the project, it will return a string “No commL.dll”.
Result = “No commL.dll”
Note: The register generated by ItemsSend function to send each Item is:
China -> L2_C
Rest -> AG ( 102E scale version or later is required )V 1.0.0.4_EN 7

SCALE STRUCTURE
This structure defines the scale with which the communication is stablished.
typedef struct _Scale
{
int masterAddress;
LPWSTR ipAddress;
int txPort;
int rxPort;
LPWSTR model;
LPWSTR display;
LPWSTR section;
int group;
LPWSTR logsPath;
}Scale;
Where:
- masterAddress: Logic address of the scale (Master Address). The registers will be
modified to assign this logic address.
Data type: int -> Integer without sign (4 bytes).
- ipAddress: IP address of the scale.
Data type: LPWSTR -> Wide character string.
- txPort: Port of the scale where we must connect for sending data to the scale.
Data type: int -> Integer without sign (4 bytes). (Is not in used)
- rxPort: Port of the scale where we must connect for receiving data to the scale.
Data type: int -> Integer without sign (4 bytes).
- model: Define the scale model.
Values:
500RANGE -> Is a Gamma 500 scale.
LSERIES -> Is a L series scale.
Data type: LPWSTR -> Wide character string.
- display: Type of scale display. (Is not in used)
Values:
ALPHANUMERIC -> Scale with alphanumeric display
GRAPHIC -> Scale with graphic display
Data type: LPWSTR -> Wide character string.
- section: Sections associated to the scale. If there are multiple sections they must be
separated with commas (“,”).(Is not in used)
Data type: LPWSTR -> Wide character string.
- group: Group of the scale. The registers will be modified to assign this Group number.
Data type: int -> Integer without sign (4 bytes).
- logsPath: Path for the logs file, this file have all the registers of communication. If it is
empty the communication logs will not be recorded. (It is not used)
Data type: LPWSTR -> Wide character string.V 1.0.0.4_EN 8

ITEM STRUCTURE
This is the structure to define the article data to be sent to the scale.
typedef struct _Item
{
int code;
int directKey;
double price;
LPWSTR name;
int type;
int section;
LPWSTR expiryDate;
int alterPrice;
int number;
int priceFactor;
LPWSTR textG;
}Item;
Where:
- code : Article Identification code (maxValue = 999999).
Data type: int -> Integer without sign (4 bytes).
- directKey: Direct key associated to the article (maxValue = 999).
Data type: int -> Integer without sign (4 bytes).
- price: Article price (maxValue= 9999,99). Data type: double(8 bytes)
- name: Article name (maxLength=36 bytes, for China).
Data type: LPWSTR -> Wide character string.
- type: Type of article. Data type: int -> Integer without sign (4 bytes).
0-> Weighed
1-> Non Weighed
- section: Article section. Data type: int -> Integer without sign (4 bytes).
- expiryDate: Best before date (format: dd/MM/yyyy).
Data type:LPCSTR -> Character string constant.
- alterPrice: Allows to modify the item price. Data type: int->Integer without sign (4
bytes). 0 -> Allows to modify the price.
1 -> Don’t allow to modify the price.
- number: PLUNumber, 9 digits number to be printed in the label
(maxValue=999999999)
Data type: int -> Integer without sign (4 bytes).
- priceFactor: Determines the weight base of the price.
Data type: int -> Integer without sign (4 bytes).
0 -> Yuan/kg
1 -> Yuan/100g
2 -> Yuan/500g
- textG: Item G text. (maxLegth = 1024 bytes). Data type: Byte array. (It is not used
*/
User avatar
mol
Posts: 3718
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: How to call function from .dll library?

Post by mol »

Wow! I'll test as soon as possible. Now is 11 pm, my wife is sitting by me :-)
User avatar
mol
Posts: 3718
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: How to call function from .dll library?

Post by mol »

Hi Krzysztof!
You've made some mistakes in the loop reading Items - with data types
I've changed and now all works OK

Code: Select all

  for (n = 0; n < nItems; ++n)
      {
        hb_arrayGet(pArray, n+1, pSubArray);
        
        it[n].code        = (INT)    hb_arrayGetNI   (pSubArray,  1);
        it[n].directKey   = (INT)    hb_arrayGetNI   (pSubArray,  2);
        it[n].price       = (DOUBLE) hb_arrayGetND   (pSubArray,  3);
        it[n].name        = (LPWSTR) HMG_arrayGetCPtr(pSubArray,  4);
        it[n].type        = (INT)    hb_arrayGetNI   (pSubArray,  5);
        it[n].section     = (INT)    hb_arrayGetNI   (pSubArray,  6);
        it[n].expiryDate  = (LPWSTR) HMG_arrayGetCPtr(pSubArray,  7);
        it[n].alterPrice  = (INT)    hb_arrayGetNI   (pSubArray,  8);
        it[n].number      = (INT)    hb_arrayGetNI   (pSubArray,  9);
        it[n].priceFactor = (INT)    hb_arrayGetNI   (pSubArray, 10);
        it[n].textG       = (LPWSTR) HMG_arrayGetCPtr(pSubArray, 11);
      }
     
Thank you again!
KDJ
Posts: 243
Joined: Mon Sep 05, 2016 3:04 am
Location: Poland

Re: How to call function from .dll library?

Post by KDJ »

I am pleasantly surprised that I didn't make other mistakes.
User avatar
apais
Posts: 440
Joined: Fri Aug 01, 2008 6:03 pm
DBs Used: DBF
Location: uruguay
Contact:

Re: How to call function from .dll library?

Post by apais »

Bravo !
Now I've learned how to traslate a Harbour array to a C structure.
Thank you
Angel Pais
Web Apps consultant/architect/developer.
HW_apache (webserver modules) co-developer.
HbTron (Html GUI for harbour desktop hybrid apps) co-developer.
https://www.hbtron.com
User avatar
mol
Posts: 3718
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: How to call function from .dll library?

Post by mol »

apais wrote: Sun Jun 18, 2017 4:37 pm Bravo !
Now I've learned how to traslate a Harbour array to a C structure.
Thank you
Me too!
Post Reply