What You'll Learn
- C strings vs C++ strings
- Function pointers & C callbacks
- Wrapping C APIs in RAII classes
- unique_ptr with custom deleters
Working with C Libraries
C++ was designed to interoperate with C. Many critical libraries (SQLite, OpenSSL, POSIX, zlib) are written in C. This lesson teaches you how to use C APIs safely from C++, convert between C and C++ types, and wrap raw C resources in RAII classes.
C Strings, Memory & Type Conversion
C strings are null-terminated char arrays. C++ strings are std::string objects. Use .c_str() to pass C++ strings to C APIs, and the std::string constructor to go the other way. Never mix malloc/free with new/delete — they use different memory managers.
Common Mistake: Calling delete on memory allocated with malloc, or free on memory from new. This is undefined behaviour — always match the allocation/deallocation pair.
C/C++ String Conversion
Convert between C strings and std::string, use C memory functions
#include <iostream>
#include <cstring> // C string functions in C++
#include <cstdlib> // C memory functions
#include <string>
using namespace std;
int main() {
// C-style strings (null-terminated char arrays)
const char* greeting = "Hello from C!";
char buffer[50];
// C string functions (still useful in C++)
strcpy(buffer, greeting);
strcat(buffer, " Welcome.");
cout << "C string: " << buffer << endl;
cout << "Length: " << strlen(buffer) << endl;
// Co
...C-Style Callbacks & Function Pointers
C APIs use function pointers for callbacks — qsort, event handlers, and plugin systems all take function pointer arguments. In C++, you can pass regular functions or static member functions, but not lambdas with captures (they have state, which a raw pointer can't represent).
Pro Tip: Stateless lambdas (no captures) can convert to function pointers automatically: CompareFunc f = [](const void* a, const void* b) {...}
C Callbacks
Use function pointers with qsort and event handlers
#include <iostream>
#include <functional>
#include <cstdlib>
using namespace std;
// C-style callback — function pointer
typedef int (*CompareFunc)(const void*, const void*);
// C comparison function for qsort
int compareInts(const void* a, const void* b) {
return (*(const int*)a) - (*(const int*)b);
}
int compareDesc(const void* a, const void* b) {
return (*(const int*)b) - (*(const int*)a);
}
// C-style event system with callbacks
typedef void (*EventHandler)(int code, const char*
...RAII Wrappers for C Resources
The safest way to use C APIs in C++ is to wrap them in RAII classes. The constructor acquires the resource (fopen, malloc, sqlite3_open), and the destructor releases it. This guarantees cleanup even when exceptions are thrown.
For one-off wrapping, unique_ptr with a custom deleter is even simpler — no class needed, just specify the cleanup function.
RAII C Wrappers
Wrap FILE* and malloc in safe C++ classes
#include <iostream>
#include <string>
#include <memory>
#include <cstdio>
using namespace std;
// Wrapping C APIs in RAII C++ classes
// Example 1: RAII wrapper for FILE*
class File {
FILE* fp;
string path;
public:
File(const string& path, const string& mode)
: fp(fopen(path.c_str(), mode.c_str())), path(path) {
if (!fp) throw runtime_error("Cannot open: " + path);
cout << "Opened: " << path << endl;
}
~File() {
if (fp) {
fclose(f
...Quick Reference
| Task | Approach |
|---|---|
| C++ → C string | str.c_str() |
| C → C++ string | string(cstr) |
| Callback | Function pointer or stateless lambda |
| Wrap C resource | RAII class or unique_ptr + deleter |
| malloc memory | Always free() — never delete |
Lesson Complete!
You can now safely call C libraries from C++, handle callbacks, and wrap raw resources in RAII classes.
Sign up for free to track which lessons you've completed and get learning reminders.