1

INTRODUCTION I'm reteaching myself C++ after having taken a college class. I recently acquired an Arcus Performax PMX-4EX-SA-TB9 stepper motor controller that has a USB connection which I plan to use. The company provides software to control the stepper manually using their proprietary code and also provides a terminal within their software where you can send single lines of code to the controller to control the stepper. You can control acceleration and top speed and all kinds of stuff. This was fun to play with but now I want to go further. The online manual talks about using C++ to write your own programs for the stepper and I downloaded the files I believe I need. I have a DLL file, a lib file, and a header file. I have thus learned that the DLL file is a Dynamic Link Library which is used during runtime of the executable. I have read through the lib file and the header file and found what I think are some function declarations in the header file that resemble some of the motor commands. I will insert the header file below.

MY QUESTION

Can I use the DLL file along with the lib and header to control this device using what I can see of the functions in the header file? How do I load this all up? Would anyone be willing on writing a short little example using the fnPerformaxComDoMove function included down below? So that I may go from there? I am using Visual Studio C++ 2013 and I've done online tutorials on creating and using a DLL I've made myself but those all seem so simple compared to this one.

MY MEAGER UNDERSTANDING

I believe since I'm being provided with a DLL, header, and lib file, that I will be using the _declspec(dllexport) definition and not the import version. All the function declarations start like "BOOL" then "PERFORMAXCOM_API" then "_stdcall" and I'm only used to seeing a type then a function name then the arguments in parentheses. What does "PERFORMAX_API" and "_stdcall" mean, in front of all the different functions? I understand that DWORD is double word and is a 32bit integer but some of the arguments ask for an axis, like x,y, and z...why would they want a number when they could've just asked for a char? Thank you so much to anyone that can help me with any information. I want so badly to learn how to use this.

HEADER

    #ifdef PERFORMAXCOM_EXPORTS
    #define PERFORMAXCOM_API __declspec(dllexport)
    #else
    #define PERFORMAXCOM_API __declspec(dllimport)
    #endif

    extern PERFORMAXCOM_API int nPerformaxCom;

    #ifdef __cplusplus
    extern "C" {
    #endif

    PERFORMAXCOM_API int fnPerformaxCom(void);

    //USB reset

    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComUSBReset(IN HANDLE pHandle);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComFlush(IN HANDLE pHandle);

    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComGetNumDevices(OUT LPDWORD         lpNumDevices);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComGetProductString(IN DWORD dwNumDevices, OUT LPVOID lpDeviceString, IN DWORD dwOptions);    
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComOpen(IN DWORD dwDeviceNum, OUT HANDLE* pHandle);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComClose(IN HANDLE pHandle);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComSetTimeouts(IN DWORD dwReadTimeout, DWORD dwWriteTimeout);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComSendRecv(IN HANDLE pHandle, IN LPVOID wBuffer, IN DWORD dwNumBytesToWrite,IN DWORD dwNumBytesToRead,OUT LPVOID rBuffer);

    signed int PERFORMAXCOM_API _stdcall fnPerformaxMove(IN HANDLE pHandle, 
                                                        IN int commandCode, 
                                                        IN int axes,
                                                IN int moveDir,
                                                IN long *value,
                                                IN int modelCode);

    signed int PERFORMAXCOM_API _stdcall fnPerformaxCommandReply(IN HANDLE pHandle, 
                                                         IN char *command, 
                                                         IN char *reply);

    signed int PERFORMAXCOM_API _stdcall fnPerformaxIO(IN HANDLE pHandle, 
                                                IN int commandCode, 
                                                IN int bitNumber,
                                                IN long *value,
                                                IN int modelCode);

    signed int PERFORMAXCOM_API _stdcall fnPerformaxMotorStat(IN HANDLE pHandle, 
                                                IN int commandCode, 
                                                IN int axes,
                                                IN long *value,
                                                IN int modelCode);

    signed int PERFORMAXCOM_API _stdcall fnPerformaxSpeedAccel(IN HANDLE pHandle, 
                                                       IN int commandCode, 
                                                       IN int axes,
                                                       IN long *value,
                                                       IN int modelCode);

    signed int PERFORMAXCOM_API _stdcall fnPerformaxGeneral(IN HANDLE pHandle, 
                                                    IN int commandCode, 
                                                    IN int axes,
                                                    IN long *value,  
                                                    IN int modelCode);


    long PERFORMAXCOM_API _stdcall fnPerformaxComGetAxisStatus(IN HANDLE pHandle,DWORD dwAxisNumber);
    long PERFORMAXCOM_API _stdcall fnPerformaxComGetPulseSpeed(IN HANDLE pHandle,DWORD dwAxisNumber);
    long PERFORMAXCOM_API _stdcall fnPerformaxComGetPulsePos(IN HANDLE pHandle,DWORD dwAxisNumber);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComSetPulsePos(IN HANDLE pHandle,DWORD dwAxisNumber, DWORD pos);
    long PERFORMAXCOM_API _stdcall fnPerformaxComGetEncoderPos(IN HANDLE pHandle,DWORD dwAxisNumber);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComSetEncoderPos(IN HANDLE pHandle,DWORD dwAxisNumber, DWORD pos);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComSetPolarity(IN HANDLE pHandle,DWORD dwAxisNumber,DWORD dwPolarity);
    long PERFORMAXCOM_API _stdcall fnPerformaxComGetPolarity(IN HANDLE pHandle,DWORD dwAxisNumber);
    long PERFORMAXCOM_API _stdcall fnPerformaxComGetDIOSetup(IN HANDLE pHandle);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComSetDIOSetup(IN HANDLE pHandle, DWORD dio_setup);
    long PERFORMAXCOM_API _stdcall fnPerformaxComGetDIO(IN HANDLE pHandle);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComGetDIOBit(IN HANDLE pHandle,DWORD bitn);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComSetDIO(IN HANDLE pHandle,DWORD dio_value );
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComSetDIOBit(IN HANDLE pHandle,DWORD bitn,DWORD bitv );
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComDoHome(IN HANDLE pHandle,
                                                               DWORD axis,
                                                               DWORD dir,
                                                       DWORD low_speed,
                                                       DWORD high_speed,
                                                       DWORD accel_time,
                                                       DWORD decel_time,
                                                       DWORD search_mode,
                                                       DWORD ramp_mode);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComDoMove(IN HANDLE pHandle,
                                                       DWORD axisn,
                                                       DWORD target,
                                                       DWORD low_speed,
                                                       DWORD high_speed,
                                                       DWORD accel_time,
                                                       DWORD decel_time);
    BOOL PERFORMAXCOM_API _stdcall fnPerformaxComStop(IN HANDLE pHandle,
                                                       DWORD axisn,
                                                       DWORD ramp_stop);






    #ifdef __cplusplus
    }
    #endif
user2701295
  • 53
  • 1
  • 5

2 Answers2

1

When you use the header file in a project PERFORMAXCOM_API is going to become __declspec(dllimport) so each function is declared as a DLL import. _stdcall is the calling convention for each of the functions. Basically you can just ignore these details and write code to call the functions.

ScottMcP-MVP
  • 10,337
  • 2
  • 15
  • 15
  • So basically I could just call the function by typing: fnPerformaxComStop(IN HANDLE pHandle, DWORD axisn, DWORD ramp_stop); with the arguments replaced, as soon as I understand what IN HANDLE pHandle is, like this? fnPerformaxComStop(someHandle, someAxisn, someRamp) – user2701295 Jun 27 '14 at 14:04
  • 1
    Yes, and add the .lib file to your linker settings. This is really no different than the DLL tutorial you studied. – ScottMcP-MVP Jun 27 '14 at 16:09
  • I added all those within Virtual Studio like in the tutorials. My bewilderment stems from figuring out what the arguments are asking for. For instance, I want to call fnPerformaxComDoMove but I don't know what IN HANDLE phandle is...or it's type. I have looked through the header file and lib file that aren't really helping. The next argument of that function is DWORD axisn, which is of the double word type that is 32 bits but is it asking for x,y,z, or u? or a number? The other arguments are self explanatory to me I believe but I can't test it until I can get at least one function to work. – user2701295 Jun 27 '14 at 17:43
  • To understand the arguments you will have to use the manufacturer's documentation or sample code. – ScottMcP-MVP Jun 27 '14 at 19:00
  • I've written a complete C# API that wraps the ARCUS Performax DLL for the DMX series (USB) stepper controller. It's a great system and worth your effort to learn. – Redgum Jul 01 '14 at 15:49
  • 1
    Got whacked by the 5-minute timer. I added that the HANDLE is a pointer to the ARCUS device. It's obtained by making a call to the OPEN() method. You'll need the device HANDLE to call other methods such as MOVE() because there can be more than 1 USB stepper device. All the parameters in these methods specify is the variable type and use. – Redgum Jul 01 '14 at 15:58
  • Thank you for your reply, Redgum. So the open method, BOOL PERFORMAXCOM_API _stdcall fnPerformaxComOpen(IN DWORD dwDeviceNum, OUT HANDLE* pHandle); would be called like this? fnPerformaxComOpen(argumentsGoHere); and it would return a pointer which held the address of the controller? Then I would make a call to some of the move commands, using that pointer as the phandle? – user2701295 Jul 01 '14 at 19:23
  • So here is where I'm at so far. I have VS 2010 including the folder with the header, and i'm set up to link to the lib file. My .cpp file is including "stdafx.h", , , and I have int main() and now I'm working on coming up with some code to pull in the DLL that I have in the project directory so I can use the functions within. It is my understanding that the header file contains function prototypes. Now I need to open my only device so I can get it's handle which is a pointer, that way I can call the move function and I can go from there. – user2701295 Jul 01 '14 at 20:01
  • No code is required to "pull in the DLL". Linking to the lib takes care of that. The DLL will be loaded from the same directory that contains the exe. That's usually ..\debug or ..\release below the project directory. – ScottMcP-MVP Jul 01 '14 at 20:29
1

The method prefixes __declspec(dllimport) and __declspec(dllexport) are language extensions from Microsoft which instructs the compiler which symbols are imported or exported.

The _stdcall is a calling convention of MSVC compiler.

Stackoverflow has already got better replies, here are the links which can help you to get very clear answers to your questions. It will take a few minutes to go through.

What is __stdcall?

what does __declspec(dllimport) really mean?

Regarding your questions on Axes, a char is also of type number (same as integer) which accept smaller values (byte syze). But, a microprocessor in such a hardware you are using will perform much faster if the size of data type is same as the microprocessor architecture. if Arcus Performax PMX-4EX-SA-TB9 is a 32-bit hardware (which most of the hardware in today's world are, DWORD will perform much faster than char.

Hope this helps.

Regards Kajal

Community
  • 1
  • 1
Kajal Sinha
  • 1,565
  • 11
  • 20