Using C++ edition components in plain C

Introduction

The C++ editions can be used from plain C. The library itself exports plain C interfaces.

Setup

In the C++ editions of products, there are two types of libraries. The dynamically and statically linked libraries. The dynamically linked libraries will not have an "s" at the end of the library name while for statically linked it will. For example, IPWorks SSH would have ipworksssh22.lib as its dynamically linked library and ipworksssh22s.lib as its statically linked library.

When using the statically linked library, you must called the Static Initialization method. This method is in the form of ProductName_ComponentName_StaticInit(). For example, the static initialization method for the SFTP component in IPWorks SSH would be IPWorksSSH_SFTP_StaticInit().

IPWorksSSH_SFTP_StaticInit(NULL);

When first setting up the project the header file for the product will need to be included. This header file will be found in the include folder found in the installation folder. In the include folder there will be multiple header files. One overall header file (ex. ipworksssh.h) and one for each component (ex. sftp.h). It is only necessary to include the overall header file as it will include all the individual header files with it. The header files has the necessary typedefs and function declarations to use the components.

Initializing the Component

The Create method creates a new instance of the component. This method is in the form ProductName_ComponentName_Create. For example, the create method in for the SFTP component in IPWorks SSH would be IPWorksSSH_SFTP_Create(PIPWORKSSSH_CALLBACK lpSink, void *lpContext, char *lpOemKey, int opts). The create method takes the event sink callback function (discussed in the next section), the object reference that represents this instance, the runtime license (if being used), and the options (typically 0). For example, the SFTP component would be initialized like this:

void* m_pObj;
m_pObj = IPWorksSSH_SFTP_Create(SFTPEventSink, (void*)m_pObj, (char*)"OEM_KEY or EMPTY", 0);

In the example above, m_pObj now represents a single instance of the component and will be passed when making method calls. For example, the SFTP components list directory method would look like this:

ipworksssh_sftp_listdirectory(m_pObj);

Implementing Events

When the SFTP_Create method is called, the "SFTP_CALLBACK lpSink" parameter defines the callback function used to fire events through. The SFTPEventSink method within the header file contains the available event types, IDs, and parameters and can be added to the program to handle events. Using the switch statement in the SFTPEventSink can avoid creating/implementing the Fire*** methods. For example:

static int IPWORKSSSH_CALL SFTPEventSink(void* lpObj, int event_id, int cparam, void* param[], int cbparam[]) {
	int ret_code = 0;

	switch (event_id) {
	case EVENT_CONNECTED: {
		SFTPConnectedEventParams e = { (int)IPH64CAST(param[0]), (char*)IPH64CAST(param[1]), 0 };
    //Do Something Here
		break;
	}
	case EVENT_CONNECTIONSTATUS: {
		SFTPConnectionStatusEventParams e = { (char*)IPH64CAST(param[0]), (int)IPH64CAST(param[1]), (char*)IPH64CAST(param[2]), 0 };
		//Do Something Here
    break;
	}
	...
}
return ret_code;
}

Compilation

The program can be compiled on a Unix/Linux system or on Windows just like any other C program. For Unix/Linux a good choice is gcc/g++. On Windows, Visual Studio includes a C compiler by the name of cl.exe which can be find in YourVSDirectory/VC/bin. Make sure to compile with a reference to the library that is being used. An example of compiling the SFTP program can be found here:

cl.exe /Tc .\sftp_demo.c .\ipworksssh20s.lib

Full Example

A full example might look something like this:

#include <stdio.h>
#include <./ipworksssh.h>


static int IPWORKSSSH_CALL SFTPEventSink(void* lpObj, int event_id, int cparam, void* param[], int cbparam[]) {
	int ret_code = 0;

	switch (event_id) {
	case EID_SFTP_CONNECTED: {
		SFTPConnectedEventParams e = { (int)IPH64CAST(param[0]), (char*)IPH64CAST(param[1]), 0 };
		break;
	}
	case EID_SFTP_CONNECTIONSTATUS: {
		SFTPConnectionStatusEventParams e = { (char*)IPH64CAST(param[0]), (int)IPH64CAST(param[1]), (char*)IPH64CAST(param[2]), 0 };
		break;
	}
	case EID_SFTP_DIRLIST: {
		SFTPDirListEventParams e = { (char*)IPH64CAST(param[0]), (char*)IPH64CAST(param[1]), (int)IPH64CAST(param[2]), *(int64*)IPH64CAST(param[3]), (char*)IPH64CAST(param[4]), (int)IPH64CAST(param[5]), 0 };
		
		//Can optionally list through event
		//printf("File: %s\n",e.DirEntry);
		break;
	}
	case EID_SFTP_DISCONNECTED: {
		SFTPDisconnectedEventParams e = { (int)IPH64CAST(param[0]), (char*)IPH64CAST(param[1]), 0 };
		break;
	}
	case EID_SFTP_ENDTRANSFER: {
		SFTPEndTransferEventParams e = { (int)IPH64CAST(param[0]), (char*)IPH64CAST(param[1]), (char*)IPH64CAST(param[2]), 0 };
		break;
	}
	case EID_SFTP_ERROR: {
		SFTPErrorEventParams e = { (int)IPH64CAST(param[0]), (char*)IPH64CAST(param[1]), (char*)IPH64CAST(param[2]), (char*)IPH64CAST(param[3]), 0 };
		break;
	}
	case EID_SFTP_SSHKEYBOARDINTERACTIVE: {
		SFTPSSHKeyboardInteractiveEventParams e = { (char*)IPH64CAST(param[0]), (char*)IPH64CAST(param[1]), (char*)IPH64CAST(param[2]), (char*)IPWorksSSH_EvtStr(param[3], 0, NULL, 1), (int)IPH64CAST(param[4]), 0 };
		param[3] = (void*)(e.Response);
		break;
	}
	case EID_SFTP_SSHSERVERAUTHENTICATION: {
		SFTPSSHServerAuthenticationEventParams e = { (char*)IPH64CAST(param[0]), (int)IPH64CAST(cbparam[0]), (char*)IPH64CAST(param[1]), (char*)IPH64CAST(param[2]), (char*)IPH64CAST(param[3]), (char*)IPH64CAST(param[4]), (char*)IPH64CAST(param[5]), (int)IPH64CAST(param[6]), 0 };
		e.Accept = 1; // true
		param[6] = (void*)(e.Accept);
		break;
	}
	case EID_SFTP_SSHSTATUS: {
		SFTPSSHStatusEventParams e = { (char*)IPH64CAST(param[0]),  0 };
		printf("%s\n", e.Message);
		break;
	}
	case EID_SFTP_STARTTRANSFER: {
		SFTPStartTransferEventParams e = { (int)IPH64CAST(param[0]), (char*)IPH64CAST(param[1]), (char*)IPH64CAST(param[2]), 0 };
		break;
	}
	case EID_SFTP_TRANSFER: {
		SFTPTransferEventParams e = { (int)IPH64CAST(param[0]), (char*)IPH64CAST(param[1]), (char*)IPH64CAST(param[2]), *(int64*)IPH64CAST(param[3]), (int)IPH64CAST(param[4]), (char*)IPH64CAST(param[5]), (int)IPH64CAST(cbparam[5]), (int)IPH64CAST(param[6]), 0 };
		break;
	}

	}
	return ret_code;
}

void* m_pObj;

int main()
{
	int ret_code = 0;
	int index;
	
	printf("Press Enter to continue: ");
	getchar();
	
	IPWorksSSH_SFTP_StaticInit(NULL);
	m_pObj = IPWorksSSH_SFTP_Create(SFTPEventSink, (void*)m_pObj, (char*)"OEM_KEY or EMPTY", 0);

	ipworksssh_sftp_setsshhost(m_pObj, "HOST");
	ipworksssh_sftp_setsshport(m_pObj, PORT);
	ipworksssh_sftp_setsshauthmode(m_pObj, AM_PASSWORD);
	ipworksssh_sftp_setsshuser(m_pObj, "USER");
	ipworksssh_sftp_setsshpassword(m_pObj, "PASSOWRD");

	ret_code = ipworksssh_sftp_listdirectory(m_pObj);

	if (ret_code) {
		printf(IPWorksSSH_SFTP_GetLastError(m_pObj));
    getchar()
    IPWorksSSH_SFTP_Destroy(m_pObj);
    return 1;
	}

	for (index = 0; index &lt; ipworksssh_sftp_getdirlistcount(m_pObj); index++) {
		printf("Item: %s\n", ipworksssh_sftp_getdirlistentry(m_pObj, index));
	}

	getchar();
	IPWorksSSH_SFTP_Destroy(m_pObj);
	return 0;
}

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.