A C99-compatible library for using the Twitter API from cURL
C Other
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


  .    ,--._  
 .\'-__(  )/
 \_       ;  
  \_     /        Introduction
-<__,--''  ----================================================================================--------

Tweet With C (TWC) is a C99-compatible library for using the Twitter API. It is designed to allow you, the programmer, to interact with the API at a variety of levels, from raw cURL calls to structured and typechecked functions that marshal the parameters and block until a response is given.

cURL is the sole dependency.

Basic Usage

Before you can call any twitter API functions, you must create and initialize a twc_state instance:

twc_oauth_keys Keys; // Populate with your OAuth Consumer/Token keys
// OAuth pin authentication coming eventually

twc_state Twitter;
twc_Init(&Twitter, Keys);

Now you can call any function in the Twitter API. For example, to double-check your OAuth keys are working:

twc_call_result VerifyResult = 
    twc_Account_VerifyCredentials(&Twitter, (twc_account_verifycredentials_params){});
printf("Twitter: %.*s\n", (int)VerifyResult.Data.Size, VerifyResult.Data.Ptr);

And of course, to make a tweet:

twc_call_result TweetResult = 
    twc_Statuses_Update(&Twitter, twc_ToString("just setting up my twttr"), (twc_statuses_update_params){});
printf("Twitter: %.*s\n", (int)TweetResult.Data.Size, TweetResult.Data.Ptr);

Tweet With C returns all API call results as strings (twc_string). You can parse them with your own JSON library, or you can parse them with the provided JSON parser (also used in the code generator):

json_result Result = json_Parse((char*)VerifyResult.Data.Ptr, (int)VerifyResult.Data.Size);

When you're done, to free allocated memory and do cURL cleanup, call twc_Close:


Advanced Usage

twc_InitEx takes several parameters which you can use to control how memory is allocated during library use (by default, it uses malloc and free):

twc_InitEx(&Twitter, Keys, MyErrorBuffer, sizeof(MyErrorBuffer), MyMalloc, MyFree);

If you don't want to use the provided API functions, or one doesn't yet exist for the endpoint you're trying to access, you can make calls directly:

twc_key_value_list MyParamList = NULL;
// Load up some params...
MyParamList = twc_KeyValueList_InsertSorted(ParamList, &SomeKeyValue);

twc_MakeCall(&Twitter, TWC_HTTP_GET, "https://api.twitter.com/42.0/undocumented.json", MyParamList);

In the current version of the library, all API calls are synchronous (blocking). In the future, support may be added for asynchronous calls based on cURL's support for the same.

If you can't wait, you may want to look at twitter.c to see how twc_MakeCall is implemented. All of the functions it calls are exposed in this interface, so you can use the existing helper functions in your own version of it.

  .    ,--._  
 .\'-__(  )/
 \_       ;  
  \_     /        Building
-<__,--''  ----================================================================================--------

With Makefile

The Makefile builds libtwc.a for static linking. Dynamic linking is not supported at this time.

libtwc.a is built by first building the code generator, twc_codegen. The code generator takes 2 arguments:

  • <Template file> -- file where the serialization templates are defined. Most likely code/twitter.c.

  • <API Schema> -- JSON file where the latest API schema is stored. Most likely api.json.

New API schemas may be generated by running the TwitterDoc script. Be aware that future revisions of the Twitter API may introduce parameters that do not yet have corresponding types in this library, or endpoints which require different ways of making requests.

The version of api.json included in this repository is always guaranteed to produce good code when given to the code generator. Similarly, the twitter_api.c and twitter_api.h provided with the repository are guaranteed to be working productions based on the api.json in the repository. If for some reason the code generator does not work for you, they are your backup plan.

With Windows

To build on Windows, you will need either Visual Studio with C++ support installed, or the Visual C++ Build Tools.

Only compiling with VS 2015 has been tested. Later versions should be fine, earlier versions may need additional support.

The command-line build tools are only available once vcvarsall.bat from your VS installation has been run. For many Visual Studio installations, it may be easier to simply use the 'Visual Studio Command Prompt' shortcut that is often created when it installs. If this is not possible, or you wish to run it from an existing prompt, look for vcvarsall.bat in a directory similar to C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC.

After that, you can simply execute build.bat from the directory where you cloned the repository.

  .    ,--._  
 .\'-__(  )/
 \_       ;  
  \_     /        Contributing
-<__,--''  ----================================================================================--------

Pull requests and issues are always welcome! However, there are a few things to understand before you attempt to start contributing:

  • Use of a code generator results in some unorthodox constructs throughout the codebase. If something seems suspect, please make sure it is not just a benign side effect of code generation, formatting, etc.

  • The code style for this project is a bit unusual. However, please try to follow it in your contributions so that the project remains internally consistent. See below for guidelines.

Code Style

Types are snake_case. e.g. twc_string.

Asterisk goes with the type. e.g. const char*.

Option types get a $ at the end. e.g. twc_string$.

Variables and struct fields are PascalCase. e.g. State->Keys

To avoid namespace pollution, all functions exported from the library are prefixed with twc_ and thereafter use PascalCase. e.g. twc_MakeCall

For readability, separate parts of a function name where you might use a namespace separator in C++. For example, twc_KeyValueList_Append and twc_KeyValueList_InsertSorted are two operations on a twc_key_value_list, and so are in the same conceptual 'namespace'.

Prefer verbosity over abbreviation. Code explains itself better if the names are readable and make sense in context.

Prefer explicit over implicit. Invisible behavior makes for invisible bugs.

Prefer stack over heap. Most allocations are small and last the lifetime of the function call. Security problems can be avoided by careful use of length parameters. Clients may not be using the CRT heap.

Functions that write to a buffer parameter should also return the amount of space in the buffer they use up, and should work correctly if the buffer passed is NULL.

Clever is good, but simple is better.

Simple is good, but robust is better.

Robust is good, but maintainable is better.

Tradeoffs are contextual.

Code is data.

Go forth, and contribute.