soufasoufa33 | Bonjour,
Voilà je suis devant un problème qui m'empêche d'avancer, je vais aller step par step pour l'exposer correctement dans l’espérance de trouver de l'aide.
J'ai reçu le code source d'un programme exemple codé en C++ qui permet la communication avec un appareil, ce programme utilise des fonctions présentes dans une librairie .dll mais je n'ai pas la documentation de cette API pour pouvoir l'utiliser.
Mon but c'est de communiquer avec cette appareil en utilisant un programme qui sera fait avec Windev (Je sais utiliser WLangage de Windev si j'ai une librairie .dll à condition que cette librairie soit composée de fonctions simples e.g MaFonction(Param1,Parm2,...) et les paramètres sont de types usuels.).
Or les fonctions de l'API .dll utilisées dans l'exemple que j'ai pu le compiler et l'exécuter sous forme de .exe terminal ( code source que j'ai réussi à le compiler sous Visual Studio 10) utilise, hélas, des paramètres sous forme de structures dont WLangage ne peut pas les reproduire.
Quand j’exécute l'exemple que j'ai eu , j'arrive aisément à communiquer avec cet appareil et en plus, les fonctions présentes dans ce code ont une forme simple que si je les exporte dans une .dll je pourrais les utiliser dans mon programme Windev avec WLangage. Ma question est la suivante: Comment je pourrait exporter les fonctions appelées dans le "main" de ce programme C++ le transformé et le compiler sous forme de .dll?
voici le main de ce programme:
Code :
- #include <vector>
- #include <time.h>
- #include "IO.h"
- #include "CSMARTPayout.h"
- std::vector<string> GetComPorts(); // Returns a vector containing a list of all the available ports on the host
- bool ParseKeys(CPayout* payout); // The method responsible for parsing and responding to key presses
- void DisplayCommands(); // Displays a list of commands available for this SDK
- unsigned char FormatComPort(const string& comPort); // Remove the x. COM from the COM port string
- DWORD WINAPI PollThread(LPVOID params); // The polling function, run as a seperate thread
- HANDLE StartPollThread(CPayout* payout); // The method to start the polling thread, returns a handle to it
- const int PollInterval = 250; // Interval between polls (ms)
- volatile bool IsPolling = false; // Indicates whether the poll thread should actively poll the unit
- volatile bool PollFailed = false; // Indicates whether a poll has failed, can be called by multiple threads
- #define MAX_PROTOCOL_VERSION 8 // Max protocol version supported by MAN (3/11/11).
- int main(int argc, char *argv[])
- {
- CPayout* Payout = new CPayout(); // The main class used to interface with the validator
- // Create a new thread here, this thread will not actively poll the unit until the
- // bool IsPolling is set to true.
- HANDLE payoutThread = StartPollThread(Payout);
- // Set output to std::cout
- Payout->SetOutputStream(&std::cout);
- WriteString("\n" );
- // Find out about the validator and create a connection struct to pass
- // to the validator class
- SSP_COMMAND command;
- command.BaudRate = 9600;
- command.Timeout = 1000;
- command.RetryLevel = 3;
- command.IgnoreError = 1;
- char* end;
- // Get port number
- std::vector<string> ports = GetComPorts();
- for (unsigned int i = 0; i < ports.size(); ++i)
- WriteString(ports[i]);
- string in = "";
- unsigned int portNum = 0;
- do
- {
- in = GetInputString("Select a port: " );
- portNum = strtol(in.c_str(), &end, 0);
- } while (portNum < 1 || portNum > ports.size());
- command.PortNumber = FormatComPort(ports[portNum-1]);
- // Get ssp address
- unsigned int ssp = 0;
- do
- {
- in = GetInputString("SSP Address (Default 0): " );
- ssp = strtol(in.c_str(), &end, 0);
- } while (ssp < 0 || ssp > 32 || end == in.c_str());
- command.SSPAddress = (unsigned char)ssp;
- // Get protocol version to use
- unsigned int p = 0;
- do
- {
- in = GetInputString("Protocol version: " );
- p = strtol(in.c_str(), &end, 0);
- } while (p < 1 || p > MAX_PROTOCOL_VERSION);
- // Now connect to validator
- if (Payout->ConnectToPayout(command, p, 5) && Payout->GetUnitType() == 0x06)
- {
- WriteString("Connected to MAN successfully" );
- // Display the available commands
- DisplayCommands();
- //####################################
- Payout->EnableValidator();
- WriteString("Apres Enable" );
- // Begin checking input and poll fails
- while (true)
- {
- if (!ParseKeys(Payout))
- {
- IsPolling = false;
- break; // If false break the loop
- }
- // This bool is set by the poll loop thread
- if (PollFailed)
- {
- cout << "Poll failed" << endl;
- if (Payout->ConnectToPayout(command, p, 5))
- {
- PollFailed = false;
- StartPollThread(Payout);
- }
- else
- break;
- }
- }
- }
- else if (Payout->GetUnitType() != 0x06)
- WriteString("Incorrect unit detected, this SDK supports the MAN only" );
- else
- WriteString("Failed to connect to the unit" );
- cout << "Program shutting down... ";
- // Close poll thread
- TerminateThread(payoutThread, 1);
- CloseHandle(payoutThread);
- // Delete payout
- delete Payout;
- cout << "Complete\n\nPress any key to exit..." << endl;
- _getch();
- }
- // This function searches through com ports 1 to 128 and determines if they
- // exist or not. The list of existing ports is sent as a response.
- std::vector<string> GetComPorts()
- {
- vector<string> ports;
- int index = 1;
- // Go through each possible port
- for (int i = 1; i <= 64; ++i)
- {
- char* buffer = new char[8];
- string port = "COM";
- port += itoa(i, buffer, 10);
- // First get the size
- DWORD dwSize = 0;
- LPCOMMCONFIG lpCC = (LPCOMMCONFIG) new BYTE[1];
- BOOL ret = GetDefaultCommConfig(port.c_str(), lpCC, &dwSize);
- delete [] lpCC;
- // Now test the port
- lpCC = (LPCOMMCONFIG) new BYTE[dwSize];
- ret = GetDefaultCommConfig(port.c_str(), lpCC, &dwSize);
- // If the port exists, add to the vector
- if (ret != null)
- {
- string pusher = itoa(index++, buffer, 10);
- pusher += ". ";
- pusher += port;
- ports.push_back(pusher);
- }
- delete[] buffer;
- delete [] lpCC;
- }
- return ports;
- }
- bool ParseKeys(CPayout* payout)
- {
- // If a keystroke is detected
- if (_kbhit())
- {
- // Parse the key
- switch (_getch())
- {
- case 'x': return false;
- case 'e':
- payout->EnableValidator();
- break;
- case 'd':
- payout->DisableValidator();
- break;
- case 'p':
- {
- // Toggle the polling
- if (IsPolling)
- {
- IsPolling = false;
- WriteString("Stopped polling" );
- }
- else
- {
- IsPolling = true;
- WriteString("Started polling" );
- }
- break;
- }
- case 'r':
- {
- // Stored notes
- WriteString("Notes stored:\n" );
- payout->OutputLevelInfo();
- // Recycling status of notes
- WriteString("Recycling status of notes:\n" );
- for (int i = 0; i < payout->GetNumChannels(); ++i)
- {
- cout << payout->GetUnitData()[i].Value*0.01f << " " << payout->GetUnitData()[i].Currency[0] <<
- payout->GetUnitData()[i].Currency[1] << payout->GetUnitData()[i].Currency[2] << " is ";
- (payout->GetUnitData()[i].Recycling)?cout << "being sent to storage" << endl:
- cout << "being sent to cashbox" << endl;
- }
- // Cashbox payout data
- WriteString("\nCashbox payout data:\n" );
- payout->GetCashboxPayoutOpData();
- break;
- }
- case 'h': DisplayCommands(); break;
- case 't':
- {
- payout->ResetValidator();
- payout->CloseComPort(); // Force reconnection by closing com port
- break;
- }
- case 'a':
- {
- char choice = GetInputChar("1. Standard payout\n2. Payout by Denomination\r\n" );
- if (choice == '1') // Standard payout
- {
- string s = GetInputString("Enter amount and currency to payout\nFormat is Amount Currency e.g. 10.00 CODE: " );
- // Break into 2 strings, first contains value, second currency
- string s1 = "";
- size_t pos = s.find_first_of(' ');
- if (pos == s.npos)
- {
- WriteString("Input was not in the correct format" );
- break;
- }
- s1 = s.substr(pos+1, s1.npos);
- s.erase(pos, s.npos);
- // Convert value to integer
- float value = (float)atof(s.c_str());
- // Make sure each char in the currency is uppercase and
- // only 3 chars were entered
- if (s1.length() != 3)
- {
- WriteString("Invalid currency" );
- break;
- }
- for (int i = 0; i < 3; ++i)
- s1[i] = toupper(s1[i]);
- // If the value entered isn't 0 or negative, make the payout
- if (value > 0)
- {
- payout->Payout((int)(value * 100), s1);
- }
- }
- else if (choice == '2') // Payout by Denomination
- {
- // Get the dataset info from the validator
- SUnitData* UnitData = payout->GetUnitData();
- // Create a temporary array to hold denomination info
- unsigned char* dataArray = new unsigned char[255];
- int counter = 0, temp = 0, numDenoms = 0;
- // Go through each channel and query the user on how many of each denomination
- // they want to payout.
- for (int i = 0; i < payout->GetNumChannels(); ++i)
- {
- cout << "Number of " << UnitData[i].Value*0.01f << " " << UnitData[i].Currency[0] <<
- UnitData[i].Currency[1] << UnitData[i].Currency[2] << " to payout: ";
- temp = atoi(GetInputString("" ).c_str());
- if (temp != 0) // if they have entered a number
- {
- numDenoms++; // increase number of denominations to payout
- memcpy(dataArray + counter, &temp, 2); // copy number of denominations to the data array
- counter += 2;
- memcpy(dataArray + counter, &UnitData[i].Value, 4); // copy value of denomination to data array
- counter += 4;
- // copy currency of denom to data array
- dataArray[counter++] = UnitData[i].Currency[0];
- dataArray[counter++] = UnitData[i].Currency[1];
- dataArray[counter++] = UnitData[i].Currency[2];
- }
- }
- if (numDenoms > 0) // if the user didn't enter 0 for all denominations
- {
- payout->PayoutByDenomination(numDenoms, dataArray);
- }
- delete[] dataArray; // delete temp array once command sent
- }
- else
- WriteString("Invalid input\r\n" );
- break;
- }
- case 'm':
- {
- // Empty has two choices, SMART or just empty. SMART keeps track of
- // what notes were emptied, empty does not.
- char choice = GetInputChar("1. Empty\n2. SMART Empty\n" );
- if (choice == '1')
- payout->Empty();
- else if (choice == '2')
- payout->SMARTEmpty();
- else
- WriteString("Invalid input" );
- break;
- }
- case 'c':
- {
- // Note recycling
- string s = GetInputString("Enter amount and currency to alter recycling on\nFormat is Amount Currency e.g. 10.00 CODE: " );
- // Break into 2 strings, first contains value, second currency
- string s1 = "";
- size_t pos = s.find_first_of(' ');
- if (pos == s.npos)
- {
- WriteString("Input was not in the correct format" );
- break;
- }
- s1 = s.substr(pos+1, s1.npos);
- s.erase(pos, s.npos);
- // Convert value to integer
- float value = (float)atof(s.c_str());
- // Make sure each char in the currency is uppercase and
- // only 3 chars were entered
- if (s1.length() != 3)
- {
- WriteString("Invalid currency" );
- break;
- }
- for (int i = 0; i < 3; ++i)
- s1[i] = toupper(s1[i]);
- char c = GetInputChar("1. Store note\n2. Stack note\r\n" );
- // Validation
- if ((c != '1' && c != '2'))
- {
- cout << "Invalid input" << endl;
- break;
- }
- // Convert to bool
- bool stack = atoi(&c)-1;
- // Convert value to penny value
- value *= 100;
- // Send to either cashbox or storage depending on choice
- (stack)?payout->SendNoteToCashbox((int)value, s1):payout->SendNoteToStorage((int)value, s1);
- break;
- }
- default: break;
- }
- }
- return true;
- }
- void DisplayCommands()
- {
- string s = "Command List\n";
- s += "e = enable\nd = disable\n";
- s += "p = start/stop polling\n";
- s += "a = make a payout\n";
- s += "m = empty or SMART empty the unit\n";
- s += "c = change note recycling options\n";
- s += "t = reset validator\n";
- s += "r = report\n\n";
- s += "h = display this list again\n";
- s += "x = exit\n";
- WriteString(s);
- }
- // Remove the "x. COM" from the com port string
- unsigned inline char FormatComPort(const string& portstring)
- {
- string s = portstring;
- s.erase(0, 6);
- return (unsigned char)atoi(s.c_str());
- }
- // The following section contains threading functions. Threading is used in this program
- // as it is vital that the validator is polled at regular intervals. Obviously the execution
- // of the main thread of the program needs to be halted occasionally - such as when waiting
- // for a user's input, so the polling of the validator needs to occur on a seperate thread
- // which will never be halted. The validator class looks after critical sections and thread
- // safing.
- // This function is called to create a new instance of the poll thread. The function returns a
- // handle to the thread.
- HANDLE StartPollThread(CPayout* Payout)
- {
- unsigned int hopThreadID;
- return CreateThread(NULL,
- 0,
- PollThread,
- Payout,
- NULL,
- (LPDWORD)&hopThreadID);
- }
- // This function is responsible for polling the validator at a regular interval.
- // It should be run as a seperate thread to the main execution thread.
- DWORD WINAPI PollThread(LPVOID params)
- {
- // Get validator instance from param
- CPayout* payout = reinterpret_cast<CPayout*>(params);
- // Keep looping until broken out of
- while (true)
- {
- // If the validator is actively being polled
- if (IsPolling)
- {
- // Attempt to send the poll
- if (!payout->DoPoll())
- {
- // If it fails (command can't get to validator) then set the failed poll
- // flag to true and exit the function. This will terminate the thread.
- PollFailed = true;
- return 0;
- }
- Sleep(PollInterval); // Wait for the interval
- }
- }
- return 0;
- }
|
|