Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
5 changes: 5 additions & 0 deletions crates/tests/tools/header2rdl/tests/fn_extern_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern "C"
{
unsigned int GetTickCount();
void SetLastErrorEx(unsigned a, signed b);
}
2 changes: 2 additions & 0 deletions crates/tests/tools/header2rdl/tests/fn_extern_c.h.args
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--cpp
--library test.dll
7 changes: 7 additions & 0 deletions crates/tests/tools/header2rdl/tests/fn_extern_c.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[win32]
mod Test {
#[library("test.dll")]
extern "C" fn GetTickCount() -> u32;
#[library("test.dll")]
extern "C" fn SetLastErrorEx(a: u32, b: i32);
}
42 changes: 21 additions & 21 deletions crates/tests/tools/header2rdl/tests/webview2.rdl
Original file line number Diff line number Diff line change
Expand Up @@ -474,11 +474,11 @@ mod Test {
COREWEBVIEW2_WEB_RESOURCE_REQUEST_SOURCE_KINDS_ALL = -1,
}
#[library("WebView2")]
extern fn CompareBrowserVersions(version1: PCWSTR, version2: PCWSTR, result: *mut i32) -> HRESULT;
extern "C" fn CompareBrowserVersions(version1: PCWSTR, version2: PCWSTR, result: *mut i32) -> HRESULT;
#[library("WebView2")]
extern fn CreateCoreWebView2Environment(environmentCreatedHandler: ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) -> HRESULT;
extern "C" fn CreateCoreWebView2Environment(environmentCreatedHandler: ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) -> HRESULT;
#[library("WebView2")]
extern fn CreateCoreWebView2EnvironmentWithOptions(browserExecutableFolder: PCWSTR, userDataFolder: PCWSTR, environmentOptions: ICoreWebView2EnvironmentOptions, environmentCreatedHandler: ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) -> HRESULT;
extern "C" fn CreateCoreWebView2EnvironmentWithOptions(browserExecutableFolder: PCWSTR, userDataFolder: PCWSTR, environmentOptions: ICoreWebView2EnvironmentOptions, environmentCreatedHandler: ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) -> HRESULT;
#[typedef]
struct DOUBLE {
value: f64,
Expand All @@ -501,9 +501,9 @@ mod Test {
Data4: [u8; 8],
}
#[library("WebView2")]
extern fn GetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder: PCWSTR, versionInfo: *mut LPWSTR) -> HRESULT;
extern "C" fn GetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder: PCWSTR, versionInfo: *mut LPWSTR) -> HRESULT;
#[library("WebView2")]
extern fn GetAvailableCoreWebView2BrowserVersionStringWithOptions(browserExecutableFolder: PCWSTR, environmentOptions: ICoreWebView2EnvironmentOptions, versionInfo: *mut LPWSTR) -> HRESULT;
extern "C" fn GetAvailableCoreWebView2BrowserVersionStringWithOptions(browserExecutableFolder: PCWSTR, environmentOptions: ICoreWebView2EnvironmentOptions, versionInfo: *mut LPWSTR) -> HRESULT;
#[typedef]
struct HANDLE {
value: *mut u8,
Expand Down Expand Up @@ -2211,51 +2211,51 @@ mod Test {
fn ShowSaveAsUI(&self, handler: ICoreWebView2ShowSaveAsUICompletedHandler) -> HRESULT;
}
#[library("WebView2")]
extern fn ICoreWebView2_25_ShowSaveAsUI_Proxy(This: ICoreWebView2_25, handler: ICoreWebView2ShowSaveAsUICompletedHandler) -> HRESULT;
extern "C" fn ICoreWebView2_25_ShowSaveAsUI_Proxy(This: ICoreWebView2_25, handler: ICoreWebView2ShowSaveAsUICompletedHandler) -> HRESULT;
#[library("WebView2")]
extern fn ICoreWebView2_25_ShowSaveAsUI_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
extern "C" fn ICoreWebView2_25_ShowSaveAsUI_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
#[library("WebView2")]
extern fn ICoreWebView2_25_add_SaveAsUIShowing_Proxy(This: ICoreWebView2_25, eventHandler: ICoreWebView2SaveAsUIShowingEventHandler, token: *mut EventRegistrationToken) -> HRESULT;
extern "C" fn ICoreWebView2_25_add_SaveAsUIShowing_Proxy(This: ICoreWebView2_25, eventHandler: ICoreWebView2SaveAsUIShowingEventHandler, token: *mut EventRegistrationToken) -> HRESULT;
#[library("WebView2")]
extern fn ICoreWebView2_25_add_SaveAsUIShowing_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
extern "C" fn ICoreWebView2_25_add_SaveAsUIShowing_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
#[library("WebView2")]
extern fn ICoreWebView2_25_remove_SaveAsUIShowing_Proxy(This: ICoreWebView2_25, token: EventRegistrationToken) -> HRESULT;
extern "C" fn ICoreWebView2_25_remove_SaveAsUIShowing_Proxy(This: ICoreWebView2_25, token: EventRegistrationToken) -> HRESULT;
#[library("WebView2")]
extern fn ICoreWebView2_25_remove_SaveAsUIShowing_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
extern "C" fn ICoreWebView2_25_remove_SaveAsUIShowing_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
#[guid(0x806268b8_f897_5685_88e5_c45fca0b1a48)]
interface ICoreWebView2_26: ICoreWebView2_25 {
fn add_SaveFileSecurityCheckStarting(&self, eventHandler: ICoreWebView2SaveFileSecurityCheckStartingEventHandler, token: *mut EventRegistrationToken) -> HRESULT;
fn remove_SaveFileSecurityCheckStarting(&self, token: EventRegistrationToken) -> HRESULT;
}
#[library("WebView2")]
extern fn ICoreWebView2_26_add_SaveFileSecurityCheckStarting_Proxy(This: ICoreWebView2_26, eventHandler: ICoreWebView2SaveFileSecurityCheckStartingEventHandler, token: *mut EventRegistrationToken) -> HRESULT;
extern "C" fn ICoreWebView2_26_add_SaveFileSecurityCheckStarting_Proxy(This: ICoreWebView2_26, eventHandler: ICoreWebView2SaveFileSecurityCheckStartingEventHandler, token: *mut EventRegistrationToken) -> HRESULT;
#[library("WebView2")]
extern fn ICoreWebView2_26_add_SaveFileSecurityCheckStarting_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
extern "C" fn ICoreWebView2_26_add_SaveFileSecurityCheckStarting_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
#[library("WebView2")]
extern fn ICoreWebView2_26_remove_SaveFileSecurityCheckStarting_Proxy(This: ICoreWebView2_26, token: EventRegistrationToken) -> HRESULT;
extern "C" fn ICoreWebView2_26_remove_SaveFileSecurityCheckStarting_Proxy(This: ICoreWebView2_26, token: EventRegistrationToken) -> HRESULT;
#[library("WebView2")]
extern fn ICoreWebView2_26_remove_SaveFileSecurityCheckStarting_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
extern "C" fn ICoreWebView2_26_remove_SaveFileSecurityCheckStarting_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
#[guid(0x00fbe33b_8c07_517c_aa23_0ddd4b5f6fa0)]
interface ICoreWebView2_27: ICoreWebView2_26 {
fn add_ScreenCaptureStarting(&self, eventHandler: ICoreWebView2ScreenCaptureStartingEventHandler, token: *mut EventRegistrationToken) -> HRESULT;
fn remove_ScreenCaptureStarting(&self, token: EventRegistrationToken) -> HRESULT;
}
#[library("WebView2")]
extern fn ICoreWebView2_27_add_ScreenCaptureStarting_Proxy(This: ICoreWebView2_27, eventHandler: ICoreWebView2ScreenCaptureStartingEventHandler, token: *mut EventRegistrationToken) -> HRESULT;
extern "C" fn ICoreWebView2_27_add_ScreenCaptureStarting_Proxy(This: ICoreWebView2_27, eventHandler: ICoreWebView2ScreenCaptureStartingEventHandler, token: *mut EventRegistrationToken) -> HRESULT;
#[library("WebView2")]
extern fn ICoreWebView2_27_add_ScreenCaptureStarting_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
extern "C" fn ICoreWebView2_27_add_ScreenCaptureStarting_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
#[library("WebView2")]
extern fn ICoreWebView2_27_remove_ScreenCaptureStarting_Proxy(This: ICoreWebView2_27, token: EventRegistrationToken) -> HRESULT;
extern "C" fn ICoreWebView2_27_remove_ScreenCaptureStarting_Proxy(This: ICoreWebView2_27, token: EventRegistrationToken) -> HRESULT;
#[library("WebView2")]
extern fn ICoreWebView2_27_remove_ScreenCaptureStarting_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
extern "C" fn ICoreWebView2_27_remove_ScreenCaptureStarting_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
#[guid(0x62e50381_5bf5_51a8_aae0_f20a3a9c8a90)]
interface ICoreWebView2_28: ICoreWebView2_27 {
fn get_Find(&self, value: *mut ICoreWebView2Find) -> HRESULT;
}
#[library("WebView2")]
extern fn ICoreWebView2_28_get_Find_Proxy(This: ICoreWebView2_28, value: *mut ICoreWebView2Find) -> HRESULT;
extern "C" fn ICoreWebView2_28_get_Find_Proxy(This: ICoreWebView2_28, value: *mut ICoreWebView2Find) -> HRESULT;
#[library("WebView2")]
extern fn ICoreWebView2_28_get_Find_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
extern "C" fn ICoreWebView2_28_get_Find_Stub(This: *mut IRpcStubBuffer, _pRpcChannelBuffer: *mut IRpcChannelBuffer, _pRpcMessage: PRPC_MESSAGE, _pdwStubPhase: *mut DWORD);
#[guid(0xa0d6df20_3b92_416d_aa0c_437a9c727857)]
interface ICoreWebView2_3: ICoreWebView2_2 {
fn TrySuspend(&self, handler: ICoreWebView2TrySuspendCompletedHandler) -> HRESULT;
Expand Down
19 changes: 14 additions & 5 deletions crates/tools/header2rdl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! Requires `libclang` at build and run time. On Ubuntu 22.04+ set
//! `LIBCLANG_PATH=/usr/lib/llvm-20/lib` (or the installed LLVM version).

use clang::{diagnostic::Severity, Clang, Entity, EntityKind, Index, TypeKind};
use clang::{diagnostic::Severity, Clang, Entity, EntityKind, Index, Language, TypeKind};
use std::collections::BTreeSet;
use std::path::{Path, PathBuf};

Expand Down Expand Up @@ -344,6 +344,7 @@ struct RdlFn {
name: String,
params: Vec<(String, String)>,
ret: String,
extern_c: bool,
}

struct RdlInterface {
Expand Down Expand Up @@ -451,7 +452,12 @@ fn collect(entity: Entity, collector: &mut Collector) {
}
if let Some(name) = child.get_name() {
if collector.seen.insert(name.clone()) {
if let Some(f) = collect_function(&child, name) {
// In C++ mode, a function declared inside `extern "C" { }`
// has Language::C linkage. Track this so we can emit the
// correct `extern "C" fn` ABI in the RDL.
let extern_c = collector.cpp
&& child.get_language() == Some(Language::C);
if let Some(f) = collect_function(&child, name, extern_c) {
collector.functions.push(f);
}
}
Expand Down Expand Up @@ -668,7 +674,7 @@ fn collect_enum(entity: &Entity, name: String) -> Option<RdlEnum> {
})
}

fn collect_function(entity: &Entity, name: String) -> Option<RdlFn> {
fn collect_function(entity: &Entity, name: String, extern_c: bool) -> Option<RdlFn> {
let ty = entity.get_type()?;
let ret_ty = ty.get_result_type()?;
let ret = map_type(&ret_ty);
Expand All @@ -685,7 +691,7 @@ fn collect_function(entity: &Entity, name: String) -> Option<RdlFn> {
}
}

Some(RdlFn { name, params, ret })
Some(RdlFn { name, params, ret, extern_c })
}

fn collect_interface(entity: &Entity, name: String) -> Option<RdlInterface> {
Expand Down Expand Up @@ -747,6 +753,7 @@ fn collect_interface(entity: &Entity, name: String) -> Option<RdlInterface> {
name: mname,
params,
ret,
extern_c: false,
});
}

Expand Down Expand Up @@ -1020,7 +1027,9 @@ fn emit_fn(f: &RdlFn, library: &str) -> String {
format!("#[library(\"{library}\")] ")
};

format!("{lib_attr}extern fn {}({params}){ret};", f.name)
let abi = if f.extern_c { r#""C" "# } else { "" };

format!("{lib_attr}extern {abi}fn {}({params}){ret};", f.name)
}

fn emit_interface(iface: &RdlInterface) -> String {
Expand Down