Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions book/src/call_cpp_from_rust/opaque.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ There are currently 3 kinds of opaque types that `zngur` is able to represent
These types are made available to Rust with varying sets of restrictions and tradeoffs imposed
based on your choice

For each of these types (aka. marked `#cpp_ref`, `#cpp_value`, or
For each of these types (aka. marked `#cpp_ref`, `#cpp_heap_allocated`, or
`#cpp_stack_owned`), `zngur` will generate a new type within `pub mod cpp {}`.

This module is where all generated opaque types live
Expand Down Expand Up @@ -61,9 +61,12 @@ Those problem might be solved by the `extern type` language feature.

## Opaque Heap Allocated C++ Type

Keeping C++ objects in Rust using heap allocation is supported with `#cpp_value` types.
Keeping C++ objects in Rust using heap allocation is supported with `#cpp_heap_allocated` types.
This is similar to `#cpp_ref` types. Look at the example `tutorial_cpp` for a usage example

> **NOTE**: `#cpp_value` is a deprecated alias for `#cpp_heap_allocated` and will
> emit a warning when used; new code should use `#cpp_heap_allocated`.

### Semantics of Opaque Heap Allocated Types

Heap allocated types are generated as a #[repr(C)] struct to a heap allocated pointer and destructor.
Expand Down
4 changes: 2 additions & 2 deletions book/src/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,13 +396,13 @@ In the same directory, create a `main.zng` file with the following content:
type crate::Inventory {
#layout(size = 16, align = 8);

#cpp_value "0" "::cpp_inventory::Inventory";
#cpp_heap_allocated "::cpp_inventory::Inventory";
}

type crate::Item {
#layout(size = 16, align = 8);

#cpp_value "0" "::cpp_inventory::Item";
#cpp_heap_allocated "::cpp_inventory::Item";
}
```

Expand Down
2 changes: 1 addition & 1 deletion examples/multiple_modules/aggregation/aggregation.zng
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "packet.zng";

type crate::StatsAccumulator {
#layout(size = 16, align = 8);
#cpp_value "0" "::cpp_stats::StatsAccumulator";
#cpp_heap_allocated "::cpp_stats::StatsAccumulator";
}

extern "C++" {
Expand Down
4 changes: 2 additions & 2 deletions examples/tutorial_cpp/main.zng
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ type ::std::result::Result<&str, ::std::str::Utf8Error> {
type crate::Inventory {
#layout(size = 16, align = 8);

#cpp_value "0" "::cpp_inventory::Inventory";
#cpp_heap_allocated "::cpp_inventory::Inventory";
}

type crate::Item {
#layout(size = 16, align = 8);

#cpp_value "0" "::cpp_inventory::Item";
#cpp_heap_allocated "::cpp_inventory::Item";
}

type ::std::fmt::Result {
Expand Down
3 changes: 2 additions & 1 deletion zngur-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ fn main() {
.with_cpp_file(cpp_file)
.with_h_file(h_file)
.with_rs_file(rs_file)
.with_zng_header_in_place_as(zng_header_in_place);
.with_zng_header_in_place_as(zng_header_in_place)
.with_warning_sink(|w| eprintln!("{w}"));
if let Some(cpp_namespace) = cpp_namespace {
zng = zng.with_cpp_namespace(&cpp_namespace);
}
Expand Down
10 changes: 8 additions & 2 deletions zngur-def/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,13 @@ pub struct ZngurMethodDetails {
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CppValue(pub String, pub String);
pub struct CppHeapAllocated(pub String);

#[derive(Debug)]
pub struct CppHeapAllocatedData {
pub bridge_fn: String,
pub cpp_type: String,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CppRef(pub String);
Expand Down Expand Up @@ -174,7 +180,7 @@ pub struct ZngurType {
pub constructor: Option<ZngurConstructor>,
pub variants: Vec<ZngurVariant>,
pub fields: Vec<ZngurField>,
pub cpp_value: Option<CppValue>,
pub cpp_heap_allocated: Option<CppHeapAllocated>,
pub cpp_ref: Option<CppRef>,
pub cpp_stack_owned: Option<CppStackOwned>,
}
Expand Down
17 changes: 10 additions & 7 deletions zngur-def/src/merge.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
AdditionalIncludes, ConvertPanicToException, CppRef, CppStackOwned, CppValue, LayoutPolicy,
ZngurConstructor, ZngurExternCppFn, ZngurExternCppImpl, ZngurField, ZngurFn,
AdditionalIncludes, ConvertPanicToException, CppHeapAllocated, CppRef, CppStackOwned,
LayoutPolicy, ZngurConstructor, ZngurExternCppFn, ZngurExternCppImpl, ZngurField, ZngurFn,
ZngurMethodDetails, ZngurSpec, ZngurTrait, ZngurType, ZngurVariant,
};

Expand Down Expand Up @@ -148,7 +148,8 @@ impl Merge for ZngurType {
));
}

self.cpp_value.merge(&mut into.cpp_value)?;
self.cpp_heap_allocated
.merge(&mut into.cpp_heap_allocated)?;
self.cpp_ref.merge(&mut into.cpp_ref)?;
self.cpp_stack_owned.merge(&mut into.cpp_stack_owned)?;

Expand Down Expand Up @@ -189,14 +190,16 @@ impl Merge for ZngurTrait {
}
}

impl Merge for CppValue {
impl Merge for CppHeapAllocated {
/// Writes the partial union of `self` and `into` to the latter.
///
/// There is no meaningful way to merge different CppValues, but we allow
/// merging the same CppValue from different sources.
/// There is no meaningful way to merge different CppHeapAllocated values, but we
/// allow merging the same CppHeapAllocated value from different sources.
fn merge(self, into: &mut Self) -> MergeResult {
if self != *into {
return Err(MergeFailure::Conflict("Cpp value mismatch".to_string()));
return Err(MergeFailure::Conflict(
"Cpp heap allocated mismatch".to_string(),
));
}
Ok(())
}
Expand Down
8 changes: 5 additions & 3 deletions zngur-generator/src/cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use std::{

use indexmap::IndexMap;
use itertools::Itertools;
use zngur_def::{CppRef, CppStackOwned, CppValue, RustTrait, ZngurFieldData, ZngurMethodReceiver};
use zngur_def::{
CppHeapAllocatedData, CppRef, CppStackOwned, RustTrait, ZngurFieldData, ZngurMethodReceiver,
};

use crate::{
ZngurWellknownTraitData,
Expand Down Expand Up @@ -525,7 +527,7 @@ pub struct CppTypeDefinition {
pub from_trait: Option<RustTrait>,
pub from_trait_ref: Option<RustTrait>,
pub wellknown_traits: Vec<ZngurWellknownTraitData>,
pub cpp_value: Option<CppValue>,
pub cpp_heap_allocated: Option<CppHeapAllocatedData>,
pub cpp_ref: Option<CppRef>,
pub cpp_stack_owned: Option<CppStackOwned>,
}
Expand Down Expand Up @@ -659,7 +661,7 @@ impl Default for CppTypeDefinition {
wellknown_traits: vec![],
from_trait: None,
from_trait_ref: None,
cpp_value: None,
cpp_heap_allocated: None,
cpp_ref: None,
cpp_stack_owned: None,
}
Expand Down
10 changes: 6 additions & 4 deletions zngur-generator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ impl ZngurGenerator {
"#
));
}
if ty_def.cpp_value.is_some() {
if ty_def.cpp_heap_allocated.is_some() {
let type_name = ty.to_string().split("::").last().unwrap().to_string();
cpp_mod_content.push_str(&format!(
r#"
Expand Down Expand Up @@ -325,9 +325,11 @@ impl ZngurGenerator {
fields,
methods: cpp_methods,
wellknown_traits,
cpp_value: ty_def.cpp_value.map(|mut cpp_value| {
cpp_value.0 = rust_file.add_cpp_value_bridge(&ty);
cpp_value
cpp_heap_allocated: ty_def.cpp_heap_allocated.map(|cpp_heap_allocated| {
CppHeapAllocatedData {
bridge_fn: rust_file.add_cpp_heap_allocated_bridge(&ty),
cpp_type: cpp_heap_allocated.0,
}
}),
cpp_ref: ty_def.cpp_ref,
cpp_stack_owned: ty_def.cpp_stack_owned,
Expand Down
4 changes: 2 additions & 2 deletions zngur-generator/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1099,9 +1099,9 @@ pub {}fn {rust_name}("#,
mangled_name
}

pub fn add_cpp_value_bridge(&mut self, ty: &RustType) -> String {
pub fn add_cpp_heap_allocated_bridge(&mut self, ty: &RustType) -> String {
let type_name = ty.to_string().split("::").last().unwrap().to_string();
let mangled_name = self.mangle_name(&format!("{ty}_cpp_value"));
let mangled_name = self.mangle_name(&format!("{ty}_cpp_heap_allocated"));
w!(
self,
r#"
Expand Down
24 changes: 12 additions & 12 deletions zngur-generator/templates/cpp_header.sptl
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ extern "C" {
uint32_t {{ discriminant }} (uint8_t* i) noexcept;
{% endif %}

{% if let Some(cpp_value) = td.cpp_value %}
::{{ self.namespace }}::ZngurCppOpaqueOwnedObject* {{ cpp_value.0 }}(uint8_t*);
{% if let Some(cpp_heap_allocated) = td.cpp_heap_allocated %}
::{{ self.namespace }}::ZngurCppOpaqueOwnedObject* {{ cpp_heap_allocated.bridge_fn }}(uint8_t*);
{% endif %}

{% if !td.layout.is_stack_allocated() && !td.layout.is_only_by_ref() %}
Expand Down Expand Up @@ -368,9 +368,9 @@ namespace {{ self.namespace }} {

{{ td.render_make_box(name, self.namespace, self.crate_name) }}

{% if let Some(cpp_value) = td.cpp_value %}
inline {{ cpp_value.1 }}& cpp() {
return (*{{ cpp_value.0 }}(::{{ self.namespace }}::__zngur_internal_data_ptr(*this))).as_cpp< {{ cpp_value.1 }} >();
{% if let Some(cpp_heap_allocated) = td.cpp_heap_allocated %}
inline {{ cpp_heap_allocated.cpp_type }}& cpp() {
return (*{{ cpp_heap_allocated.bridge_fn }}(::{{ self.namespace }}::__zngur_internal_data_ptr(*this))).as_cpp< {{ cpp_heap_allocated.cpp_type }} >();
}

inline {{ name }}(::{{ self.namespace }}::ZngurCppOpaqueOwnedObject&& o) noexcept {
Expand All @@ -382,7 +382,7 @@ namespace {{ self.namespace }} {

template<typename... Args>
static inline {{ name }} build(Args&&... args) {
return {{ name }}(::{{ self.namespace }}::ZngurCppOpaqueOwnedObject::build< {{ cpp_value.1 }} >(::std::forward<Args>(args)...));
return {{ name }}(::{{ self.namespace }}::ZngurCppOpaqueOwnedObject::build< {{ cpp_heap_allocated.cpp_type }} >(::std::forward<Args>(args)...));
}
{% endif %}

Expand Down Expand Up @@ -704,9 +704,9 @@ namespace {{ self.namespace }} {

{{ td.render_make_box_ref(td.ty.path.name(), self.namespace, self.crate_name) }}

{% if let Some(cpp_value) = td.cpp_value %}
inline {{ cpp_value.1 }}& cpp() {
return (*{{ cpp_value.0 }}(reinterpret_cast<uint8_t*>(__zngur_data))).as_cpp< {{ cpp_value.1 }} >();
{% if let Some(cpp_heap_allocated) = td.cpp_heap_allocated %}
inline {{ cpp_heap_allocated.cpp_type }}& cpp() {
return (*{{ cpp_heap_allocated.bridge_fn }}(reinterpret_cast<uint8_t*>(__zngur_data))).as_cpp< {{ cpp_heap_allocated.cpp_type }} >();
}
{% endif %}

Expand Down Expand Up @@ -928,9 +928,9 @@ namespace {{ self.namespace }} {

{{ td.render_make_box_ref_only(td.ty.path.name(), self.namespace, self.crate_name) }}

{% if let Some(cpp_value) = td.cpp_value %}
inline {{ cpp_value.1 }}& cpp() {
return (*{{ cpp_value.0 }}(reinterpret_cast<uint8_t*>(__zngur_data))).as_cpp< {{ cpp_value.1 }} >();
{% if let Some(cpp_heap_allocated) = td.cpp_heap_allocated %}
inline {{ cpp_heap_allocated.cpp_type }}& cpp() {
return (*{{ cpp_heap_allocated.bridge_fn }}(reinterpret_cast<uint8_t*>(__zngur_data))).as_cpp< {{ cpp_heap_allocated.cpp_type }} >();
}
{% endif %}

Expand Down
2 changes: 1 addition & 1 deletion zngur-parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ license.workspace = true
ariadne = "0.3.0"
chumsky = { version = "=1.0.0-alpha.8", features = [] }
itertools = "0.11"
strip-ansi-escapes = "0.2.0"
zngur-def = { version = "=0.11.0", path = "../zngur-def" }

[dev-dependencies]
expect-test = "1.4.1"
strip-ansi-escapes = "0.2.0"
Loading
Loading