Пример: библиотека интернирования строк
Заголовок C++: interner.hpp
#ifndef INTERNER_HPP
#define INTERNER_HPP
#include <string>
#include <unordered_set>
class StringInterner {
std::unordered_set<std::string> strings;
public:
// Возвращает указатель на интернированную строку (действителен, пока жив interner)
const char* intern(const char* s) {
auto [it, _] = strings.emplace(s);
return it->c_str();
}
size_t count() const {
return strings.size();
}
};
#endif
Заголовочный файл C: interner.h
// interner.h (C API для FFI)
#ifndef INTERNER_H
#define INTERNER_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct StringInterner StringInterner;
StringInterner* interner_new(void);
void interner_free(StringInterner* interner);
const char* interner_intern(StringInterner* interner, const char* s);
size_t interner_count(const StringInterner* interner);
#ifdef __cplusplus
}
#endif
Реализация на C++ (interner.cpp)
#include "interner.hpp"
#include "interner.h"
extern "C" {
StringInterner* interner_new(void) {
return new StringInterner();
}
void interner_free(StringInterner* interner) {
delete interner;
}
const char* interner_intern(StringInterner* interner, const char* s) {
return interner->intern(s);
}
size_t interner_count(const StringInterner* interner) {
return interner->count();
}
}
This slide should take about 30 minutes.
Это более крупный пример. Напишите обёртку для интернера строк. Нужно будет направить слушателей к созданию непрозрачного указателя: либо напрямую объяснив приведённый ниже код, либо попросив их провести дополнительное исследование.
Предлагаемое решение
#![allow(unused)]
fn main() {
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use std::os::raw::c_char;
#[repr(C)]
pub struct StringInternerRaw {
_opaque: [u8; 0],
_pin: PhantomData<(*mut u8, std::marker::PhantomPinned)>,
}
unsafe extern "C" {
fn interner_new() -> *mut StringInternerRaw;
fn interner_free(interner: *mut StringInternerRaw);
fn interner_intern(
interner: *mut StringInternerRaw,
s: *const c_char,
) -> *const c_char;
fn interner_count(interner: *const StringInternerRaw) -> usize;
}
}
Когда сырая обёртка написана, попросите слушателей создать безопасную обёртку.