Compare commits

...

2 Commits

Author SHA1 Message Date
d2weber
63e92bed7a Add example c api usage 2026-05-18 13:08:26 +02:00
d2weber
bcc5d8107d feat: Add json rpc c++ bindings 2026-05-18 13:05:13 +02:00
5 changed files with 112 additions and 7 deletions

9
Cargo.lock generated
View File

@@ -7332,13 +7332,13 @@ dependencies = [
[[package]]
name = "yerpc"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dc24983fbe850227bfc1de89bf8cbfb3e2463afc322e0de2f155c4c23d06445"
source = "git+https://github.com/d2weber/yerpc.git?branch=d2weber%2Fc_bindings#3ba217a76b458744192d3a66624463787e6a9eee"
dependencies = [
"anyhow",
"async-channel 1.9.0",
"async-lock",
"async-trait",
"convert_case",
"futures",
"futures-util",
"log",
@@ -7351,9 +7351,8 @@ dependencies = [
[[package]]
name = "yerpc_derive"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d8560d021437420316370db865e44c000bf86380b47cf05e49be9d652042bf5"
version = "0.6.4"
source = "git+https://github.com/d2weber/yerpc.git?branch=d2weber%2Fc_bindings#3ba217a76b458744192d3a66624463787e6a9eee"
dependencies = [
"convert_case",
"darling",

View File

@@ -204,7 +204,7 @@ thiserror = "2"
tokio = "1"
tokio-util = "0.7.18"
tracing-subscriber = "0.3"
yerpc = "0.6.4"
yerpc = { git="https://github.com/d2weber/yerpc.git", branch="d2weber/c_bindings" }
[features]
default = ["vendored"]

1
deltachat-jsonrpc/c/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
generated

View File

@@ -156,7 +156,11 @@ impl CommandApi {
}
}
#[rpc(all_positional, ts_outdir = "typescript/generated")]
#[rpc(
all_positional,
ts_outdir = "typescript/generated",
c_outdir = "c/generated"
)]
impl CommandApi {
/// Test function.
async fn sleep(&self, delay: f64) {

101
example.cpp Normal file
View File

@@ -0,0 +1,101 @@
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include "deltachat-jsonrpc/c/generated/dc_json_cjson.h"
#include "deltachat-jsonrpc/c/generated/rpc.hpp"
#include "../chatmail-core-2.43.0/deltachat.h"
struct CffiTransport {
dc_jsonrpc_instance_t* jsonrpc;
char* buf_ = nullptr;
CffiTransport(dc_accounts_t* accounts) : jsonrpc(dc_jsonrpc_init(accounts)) {if (!jsonrpc) {std::abort();}}
CffiTransport(CffiTransport&& o) : jsonrpc(o.jsonrpc), buf_(o.buf_) { o.jsonrpc = nullptr; o.buf_ = nullptr; }
CffiTransport& operator=(CffiTransport&&) = delete;
CffiTransport(const CffiTransport&) = delete;
void send(const char* json) { dc_jsonrpc_request(jsonrpc, json); }
const char* read() {
if (buf_) { dc_str_unref(buf_); buf_ = nullptr; }
buf_ = dc_jsonrpc_next_response(jsonrpc);
if (!buf_) { dc_jsonrpc_unref(jsonrpc); jsonrpc = nullptr; return nullptr; }
return buf_;
}
~CffiTransport() { if (buf_) dc_str_unref(buf_); if (jsonrpc) dc_jsonrpc_unref(jsonrpc); }
void close() { send("{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":\"get_system_info\"})\")"); }
};
// struct StdioTransport {
// std::string buf_;
// void send(const char* json) { printf("%s\n", json); fflush(stdout); }
// const char* read() {
// if (!std::getline(std::cin, buf_)) return nullptr;
// return buf_.c_str();
// }
// };
// struct CffiTransport {
// dc_jsonrpc_instance_t* jsonrpc;
// CffiTransport(dc_accounts_t* accounts) : jsonrpc(dc_jsonrpc_init(accounts)) {}
// void send(const char* json) { dc_jsonrpc_request(jsonrpc, json); }
// std::string read() {
// char* r = dc_jsonrpc_next_response(jsonrpc);
// if (!r) {dc_jsonrpc_unref(jsonrpc); return {};}
// std::string s(r);
// dc_str_unref(r);
// return s;
// }
// void close() { }
// };
// ;
void logger(std::string msg) {
std::cerr << msg << std::endl;
}
int main() {
auto* raw_accounts = dc_accounts_new("my-accounts", 1);
if (!raw_accounts) return -1;
dc::Rpc<CffiTransport> rpc(CffiTransport{raw_accounts}, logger);
dc_accounts_unref(raw_accounts);
printf("arch: %s\n", rpc.get_system_info().find("arch"));
auto account_ids = rpc.get_all_account_ids();
printf("size 1: %zu\n", account_ids.size());
auto acc_id = account_ids.size() == 0 ? rpc.add_account() : account_ids.view()[0];
printf("acc_id: %u\n", acc_id);
auto a = dc::ArrayString("is_chatmail", "addr");
printf("a %zu\n", a.size());
printf("a %i\n", bool(a));
auto config = rpc.batch_get_config(acc_id, std::move(a));
printf("s: %zu\n", config.size());
printf("c: %s\n", config._c->keys[0]);
printf("c: %s\n", config._c->values[0]);
printf("c: %s\n", config._c->keys[1]);
printf("c: %s\n", config._c->values[1]);
printf("c: %s\n", config.find("addr")._c);
auto chat_id = rpc.secure_join(acc_id, "https://i.delta.chat/#AFE2503F3BDC9058CBEAB8AEBAA028AE86816AD5&v=3&i=_CmYTfzPFjM9JQV_R05mK4Qg&s=1F7dmW_qhOGytyFXUbo6who5&a=uxyjz202n%40nine.testrun.org&n=1");
// auto chat_id = 12;
auto e = rpc.get_next_event_batch();
for (size_t i = 0; i < e.size(); ++i) {
printf("kind: %i\n", e[i].event()._c->kind);
}
// {
// printf("kind: %i\n", rpc.get_next_event().event()._c->kind);
// }
auto y = rpc.send_msg(acc_id, chat_id, dc::MessageData(string_new("hi"), {}, {}, {}, {}, {}, {}, {}, {}));
// rpc.sleep(10);
auto chat = rpc.get_full_chat_by_id(acc_id, chat_id);
printf("canSend: %s\n", chat.canSend() ? "yes" : "no");
printf("isContactRequest: %s\n", chat.isContactRequest()? "yes" : "no");
}