C Language Callbacks

This example demonstrates the general pattern for implementing some standard event callbacks functions for the Chilkat “C” API.  All Chilkat “classes” what have events will use the standard Chilkat events shown in the example below (AbortCheck, PercentDone, and ProgressInfo).

This example demonstrates callbacks for an SFTP download, but the same technique applies to any other Chilkat “class”, such as HTTP, FTP2, MailMan, Rest, etc.

#include <stdio.h>

#include <C_CkSFtp.h>

BOOL myAbortCheck()
    {
    // To abort the current Chilkat method call, return non-zero.
    return 0;
    }

BOOL myPercentDone(int pctDone)
    {
    printf("Percent Done: %d\n",pctDone);

    // To abort the current Chilkat method call, return non-zero.
    return 0;
    }

void myProgressInfo(const char *name, const char *value)
    {
    printf("%s: %s\n",name,value);
    }

void ChilkatSample(void)
    {
    HCkSFtp sftp;
    BOOL success;
    int port;
    const char *hostname;
    const char *handle;

    // Declare event callbacks.
    BOOL (*fnAbortCheck)() = myAbortCheck;
    BOOL (*fnPercentDone)(int pctDone) = myPercentDone;
    void (*fnProgressInfo)(const char *name, const char *value) = myProgressInfo;

    sftp = CkSFtp_Create();

    //  Any string automatically begins a fully-functional 30-day trial.
    success = CkSFtp_UnlockComponent(sftp,"Anything for 30-day trial");
    if (success != TRUE) {
        printf("%s\n",CkSFtp_lastErrorText(sftp));
        CkSFtp_Dispose(sftp);
        return;
    }

    // Setup event callbacks.
    CkSFtp_setAbortCheck(sftp, fnAbortCheck);
    CkSFtp_setPercentDone(sftp, fnPercentDone);
    CkSFtp_setProgressInfo(sftp, fnProgressInfo);

    // Make sure to set a HeartbeatMs for AbortCheck / PercentDone callbacks..
    // Set the HeartbeatMs to 250 milliseconds.
    CkSFtp_putHeartbeatMs(sftp,250);

    //  Set some timeouts, in milliseconds:
    CkSFtp_putConnectTimeoutMs(sftp,5000);
    CkSFtp_putIdleTimeoutMs(sftp,10000);

    //  Connect to the SSH server.
    //  The standard SSH port = 22
    //  The hostname may be a hostname or IP address.

    hostname = "my-Sftp-Server-Domain-Or-IPAddress";
    port = 22;
    success = CkSFtp_Connect(sftp,hostname,port);
    if (success != TRUE) {
        printf("%s\n",CkSFtp_lastErrorText(sftp));
        CkSFtp_Dispose(sftp);
        return;
    }

    //  Authenticate with the SSH server.  Chilkat SFTP supports
    //  both password-based authenication as well as public-key
    //  authentication.  This example uses password authenication.
    success = CkSFtp_AuthenticatePw(sftp,"myLogin","myPassword");
    if (success != TRUE) {
        printf("%s\n",CkSFtp_lastErrorText(sftp));
        CkSFtp_Dispose(sftp);
        return;
    }

    //  After authenticating, the SFTP subsystem must be initialized:
    success = CkSFtp_InitializeSftp(sftp);
    if (success != TRUE) {
        printf("%s\n",CkSFtp_lastErrorText(sftp));
        CkSFtp_Dispose(sftp);
        return;
    }

    //  Open a file on the server:
    handle = CkSFtp_openFile(sftp,"hamlet.xml","readOnly","openExisting");
    if (CkSFtp_getLastMethodSuccess(sftp) != TRUE) {
        printf("%s\n",CkSFtp_lastErrorText(sftp));
        CkSFtp_Dispose(sftp);
        return;
    }

    //  Download the file:
    success = CkSFtp_DownloadFile(sftp,handle,"c:/temp/hamlet.xml");
    if (success != TRUE) {
        printf("%s\n",CkSFtp_lastErrorText(sftp));
        CkSFtp_Dispose(sftp);
        return;
    }

    //  Close the file.
    success = CkSFtp_CloseHandle(sftp,handle);
    if (success != TRUE) {
        printf("%s\n",CkSFtp_lastErrorText(sftp));
        CkSFtp_Dispose(sftp);
        return;
    }

    printf("Success.\n");


    CkSFtp_Dispose(sftp);

    }

int main()
{
  ChilkatSample();
  return 0;
}

Linking “C” Programs with the Chilkat C/C++ Libs

The Chilkat C/C++ libs are (internally) written in C++.  Therefore, when linking a “C” program with the Chilkat libs, the C++ runtime libs must be included.  This is true regardless of the operating system, whether it be Windows, MAC OS X, IOS, Linux, etc.    Different build environments will have different ways of accomplishing the task.  For example, with XCode (on Mac OS X), simply adding an empty source file having a filename with the extension “.cpp” is all that is needed.  This blog post will show how to link a “C” program on Linux with the Chilkat C/C++ static library.  The solution is to use “g++” for the link phase instead of “gcc”.  The telltale indicator that the C++ runtime libs are missing is when you see errors involving “__cxxabiv1”, such as the following:

undefined reference to `vtable for __cxxabiv1::__class_type_info'

Here is a simple C program with a simple shell script to build it correctly.

buildTest.sh (This is for 64-bit Linux. Notice that g++ is used for linking, not gcc.)

#!/bin/bash -ev

gcc -m64 -Werror -c -fmessage-length=0 -fno-stack-protector -fPIC -o"cTest.o" "cTest.c"

g++ -g0 -m64 -L"/home/chilkat/workspace/chilkat/lib64_static" ./cTest.o -o"cTest"  
    -lchilkat-9.3.0 -lpthread -lresolv

cTest.c

#include <stdio.h>
#include "../chilkat/include/C_CkFtp2.h"

void testFtp2Create(void)
    {
    HCkFtp2 ftp;
    BOOL success;

    ftp = CkFtp2_Create();

    //  Any string unlocks the component for the 1st 30-days.
    success = CkFtp2_UnlockComponent(ftp,"Anything for 30-day trial");
    if (success != TRUE) {
        printf("%s\n",CkFtp2_lastErrorText(ftp));
    }

    CkFtp2_Dispose(ftp);
    }


int main(int argc, char *argv[])
{
	testFtp2Create();
	printf("Hello World!\n");
	return 0;
}