0.3.0: fix linkage in C mode
This commit is contained in:
parent
5657325d97
commit
987152f14f
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -4,7 +4,7 @@ version = 4
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bin2hpp"
|
name = "bin2hpp"
|
||||||
version = "0.2.5"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bin2hpp"
|
name = "bin2hpp"
|
||||||
version = "0.2.5"
|
version = "0.3.0"
|
||||||
authors = ["Adam Macdonald"]
|
authors = ["Adam Macdonald"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "GPL-3.0-only"
|
license = "GPL-3.0-only"
|
||||||
|
23
README.md
23
README.md
@ -17,20 +17,35 @@ The performance (but potentially not the executable size) can be further optimis
|
|||||||
`$ bin2hpp -i my_library.dll -o c_header.h` will generate a `c_header.h` file in your current working directory containing something similar to the following:
|
`$ bin2hpp -i my_library.dll -o c_header.h` will generate a `c_header.h` file in your current working directory containing something similar to the following:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
// Generated by bin2hpp 0.2.5
|
// Generated by bin2hpp 0.3.0
|
||||||
#ifndef C_HEADER_H
|
#ifdef MY_LIBRARY_DLL_INIT
|
||||||
#define C_HEADER_H
|
|
||||||
#define MY_LIBRARY_DLL_LEN 9728
|
#define MY_LIBRARY_DLL_LEN 9728
|
||||||
const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN] = {77,90,144,0,3,0,0,0,4, ...};
|
const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN] = {77,90,144,0,3,0,0,0,4, ...};
|
||||||
#else
|
#else
|
||||||
|
#define MY_LIBRARY_DLL_LEN 9728
|
||||||
extern const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN];
|
extern const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN];
|
||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note how in **C mode** one must `#define MY_LIBRARY_DLL_INIT`, or whatever the corresponding implementation macro is for your generated header file, in exactly _one_ C source file (`*.c`, not in a `*.h` file).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
`main.c`
|
||||||
|
```c
|
||||||
|
// In any other C source files other than the first: do not redefine
|
||||||
|
#define MY_LIBRARY_DLL_INIT
|
||||||
|
#include "c_header.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return MY_LIBRARY_DLL_LEN;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Alternatively, in **C++ mode**: `bin2hpp -i my_library.dll -o cpp_header.hpp --cpp --constexpr --stdarray --i8`
|
Alternatively, in **C++ mode**: `bin2hpp -i my_library.dll -o cpp_header.hpp --cpp --constexpr --stdarray --i8`
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// Generated by bin2hpp 0.2.5
|
// Generated by bin2hpp 0.3.0
|
||||||
#if !defined(CPP_HEADER_HPP)
|
#if !defined(CPP_HEADER_HPP)
|
||||||
#define CPP_HEADER_HPP
|
#define CPP_HEADER_HPP
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
105
src/cfg.rs
105
src/cfg.rs
@ -22,7 +22,8 @@ pub struct Config {
|
|||||||
pub(crate) constness: Constness,
|
pub(crate) constness: Constness,
|
||||||
pub(crate) symbol_name: String,
|
pub(crate) symbol_name: String,
|
||||||
pub(crate) namespace: Option<String>,
|
pub(crate) namespace: Option<String>,
|
||||||
pub(crate) guard_name: String,
|
pub(crate) impl_macro: String,
|
||||||
|
pub(crate) header_guard: String,
|
||||||
pub(crate) container_type: ContainerType,
|
pub(crate) container_type: ContainerType,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +57,54 @@ pub fn parse_config_from_args(args: &CliArgs) -> Result<Config, ProgramConfigErr
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let symbol_name = match &args.symbol_name {
|
||||||
|
Some(s) => {
|
||||||
|
if s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
|
||||||
|
s.to_string()
|
||||||
|
} else {
|
||||||
|
return Err(ProgramConfigError::InvalidSymbolName(s.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let mut stem: String = match args.input_file_path.file_stem() {
|
||||||
|
Some(s) => s.to_string_lossy().to_string(),
|
||||||
|
None => {
|
||||||
|
return Err(ProgramConfigError::InvalidPath(
|
||||||
|
args.input_file_path.to_string_lossy().to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
stem.retain(|c| c.is_ascii_alphanumeric() || c == '_');
|
||||||
|
|
||||||
|
let mut ext: String = match args.input_file_path.extension() {
|
||||||
|
Some(s) => format!("_{}", s.to_string_lossy()),
|
||||||
|
None => "".to_string(),
|
||||||
|
};
|
||||||
|
ext.retain(|c| c.is_ascii_alphanumeric() || c == '_');
|
||||||
|
|
||||||
|
format!("{}{}", stem.to_ascii_uppercase(), ext.to_ascii_uppercase())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let header_guard = match output_path.file_stem() {
|
||||||
|
Some(stem) => {
|
||||||
|
format!(
|
||||||
|
"{}_{}",
|
||||||
|
stem.to_string_lossy().to_uppercase(),
|
||||||
|
if let Some(ext) = output_path.extension() {
|
||||||
|
ext.to_string_lossy().to_uppercase()
|
||||||
|
} else {
|
||||||
|
"".into()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(ProgramConfigError::InvalidPath(
|
||||||
|
output_path.to_string_lossy().to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Config {
|
Ok(Config {
|
||||||
input_file_path: args.input_file_path.clone(),
|
input_file_path: args.input_file_path.clone(),
|
||||||
output_file_path: output_path.clone(),
|
output_file_path: output_path.clone(),
|
||||||
@ -67,34 +116,7 @@ pub fn parse_config_from_args(args: &CliArgs) -> Result<Config, ProgramConfigErr
|
|||||||
},
|
},
|
||||||
language: args.language,
|
language: args.language,
|
||||||
constness: args.constness,
|
constness: args.constness,
|
||||||
symbol_name: match &args.symbol_name {
|
symbol_name: symbol_name.clone(),
|
||||||
Some(s) => {
|
|
||||||
if s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
|
|
||||||
s.to_string()
|
|
||||||
} else {
|
|
||||||
return Err(ProgramConfigError::InvalidSymbolName(s.to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let mut stem: String = match args.input_file_path.file_stem() {
|
|
||||||
Some(s) => s.to_string_lossy().to_string(),
|
|
||||||
None => {
|
|
||||||
return Err(ProgramConfigError::InvalidPath(
|
|
||||||
args.input_file_path.to_string_lossy().to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
stem.retain(|c| c.is_ascii_alphanumeric() || c == '_');
|
|
||||||
|
|
||||||
let mut ext: String = match args.input_file_path.extension() {
|
|
||||||
Some(s) => format!("_{}", s.to_string_lossy()),
|
|
||||||
None => "".to_string(),
|
|
||||||
};
|
|
||||||
ext.retain(|c| c.is_ascii_alphanumeric() || c == '_');
|
|
||||||
|
|
||||||
format!("{}{}", stem.to_ascii_uppercase(), ext.to_ascii_uppercase())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
namespace: match &args.namespace {
|
namespace: match &args.namespace {
|
||||||
Some(ns) => {
|
Some(ns) => {
|
||||||
if ns.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
|
if ns.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
|
||||||
@ -105,7 +127,7 @@ pub fn parse_config_from_args(args: &CliArgs) -> Result<Config, ProgramConfigErr
|
|||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
guard_name: match &args.guard_name {
|
impl_macro: match &args.impl_macro_name {
|
||||||
Some(guard) => {
|
Some(guard) => {
|
||||||
if guard.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
|
if guard.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
|
||||||
guard.clone()
|
guard.clone()
|
||||||
@ -114,29 +136,10 @@ pub fn parse_config_from_args(args: &CliArgs) -> Result<Config, ProgramConfigErr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut stem: String = match output_path.file_stem() {
|
format!("{}_INIT", symbol_name.to_uppercase())
|
||||||
Some(s) => s.to_string_lossy().to_ascii_uppercase(),
|
|
||||||
None => {
|
|
||||||
return Err(ProgramConfigError::InvalidPath(
|
|
||||||
args.input_file_path.to_string_lossy().to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
stem.retain(|c| c.is_ascii_alphanumeric() || c == '_');
|
|
||||||
|
|
||||||
let mut ext: String = match output_path.extension() {
|
|
||||||
Some(s) => s.to_string_lossy().to_ascii_uppercase(),
|
|
||||||
None => {
|
|
||||||
return Err(ProgramConfigError::InvalidPath(
|
|
||||||
args.input_file_path.to_string_lossy().to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ext.retain(|c| c.is_ascii_alphanumeric() || c == '_');
|
|
||||||
|
|
||||||
format!("{}_{}", stem, ext)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
header_guard: header_guard,
|
||||||
container_type: args.container_type,
|
container_type: args.container_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ pub struct CliArgs {
|
|||||||
pub(crate) constness: Constness,
|
pub(crate) constness: Constness,
|
||||||
pub(crate) symbol_name: Option<String>,
|
pub(crate) symbol_name: Option<String>,
|
||||||
pub(crate) namespace: Option<String>,
|
pub(crate) namespace: Option<String>,
|
||||||
pub(crate) guard_name: Option<String>,
|
pub(crate) impl_macro_name: Option<String>,
|
||||||
pub(crate) container_type: ContainerType,
|
pub(crate) container_type: ContainerType,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,10 +123,10 @@ pub fn parse_cli_args(args: &[String]) -> Result<CliArgs, CliParseError> {
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let guard_name = match args.iter().position(|s| *s == "--guard") {
|
let impl_macro_name = match args.iter().position(|s| *s == "--impl") {
|
||||||
Some(idx) => match args.get(idx + 1) {
|
Some(idx) => match args.get(idx + 1) {
|
||||||
Some(s) => Some(s),
|
Some(s) => Some(s),
|
||||||
None => return Err(CliParseError::MissingOperand("--guard")),
|
None => return Err(CliParseError::MissingOperand("--impl")),
|
||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
@ -237,7 +237,7 @@ pub fn parse_cli_args(args: &[String]) -> Result<CliArgs, CliParseError> {
|
|||||||
constness: constness,
|
constness: constness,
|
||||||
symbol_name: symbol_name.cloned(),
|
symbol_name: symbol_name.cloned(),
|
||||||
namespace: namespace.cloned(),
|
namespace: namespace.cloned(),
|
||||||
guard_name: guard_name.cloned(),
|
impl_macro_name: impl_macro_name.cloned(),
|
||||||
container_type: container_type,
|
container_type: container_type,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,8 @@ OUTPUT OPTIONS:
|
|||||||
|
|
||||||
--symname NAME Symbol name
|
--symname NAME Symbol name
|
||||||
--namespace NAME Namespace in which the symbol will exist (C++ mode)
|
--namespace NAME Namespace in which the symbol will exist (C++ mode)
|
||||||
--guard NAME Preprocessor macro to use for the header guard (#ifndef ...)
|
--impl NAME Preprocessor macro to use for the implementation guard
|
||||||
(default: derive from output filename)
|
in C mode (default: derive from symbol name)
|
||||||
|
|
||||||
CONTAINER TYPES:
|
CONTAINER TYPES:
|
||||||
|
|
||||||
|
@ -33,18 +33,17 @@ pub fn header(config: &Config, in_data: &[u8]) -> Result<String, HeaderGeneratio
|
|||||||
write!(
|
write!(
|
||||||
buf,
|
buf,
|
||||||
"#if !defined({}){}",
|
"#if !defined({}){}",
|
||||||
config.guard_name, config.line_ending
|
config.header_guard, config.line_ending
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
write!(buf, "#define {}{}", config.header_guard, config.line_ending).unwrap();
|
||||||
} else {
|
} else {
|
||||||
// C style
|
// C style
|
||||||
write!(buf, "#ifndef {}{}", config.guard_name, config.line_ending).unwrap();
|
write!(buf, "#ifdef {}{}", config.impl_macro, config.line_ending).unwrap();
|
||||||
}
|
}
|
||||||
write!(buf, "#define {}{}", config.guard_name, config.line_ending).unwrap();
|
|
||||||
|
|
||||||
// Includes & main content
|
// Includes & main content
|
||||||
|
|
||||||
with_includes(config, &mut buf);
|
|
||||||
with_contents(config, in_data, &mut buf)?;
|
with_contents(config, in_data, &mut buf)?;
|
||||||
|
|
||||||
// End header guard
|
// End header guard
|
||||||
@ -59,6 +58,21 @@ pub fn with_contents(
|
|||||||
in_data: &[u8],
|
in_data: &[u8],
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
) -> Result<(), HeaderGenerationError> {
|
) -> Result<(), HeaderGenerationError> {
|
||||||
|
with_includes(config, buf);
|
||||||
|
|
||||||
|
let length: usize = match config.container_type {
|
||||||
|
ContainerType::CString => in_data.len() + 1, // +1 for NUL terminator
|
||||||
|
_ => in_data.len(),
|
||||||
|
};
|
||||||
|
|
||||||
|
write!(
|
||||||
|
buf,
|
||||||
|
"{}{}",
|
||||||
|
length_define(config, length),
|
||||||
|
config.line_ending
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if config.language == Language::Cpp {
|
if config.language == Language::Cpp {
|
||||||
// C++ mode
|
// C++ mode
|
||||||
|
|
||||||
@ -73,8 +87,17 @@ pub fn with_contents(
|
|||||||
// C mode
|
// C mode
|
||||||
|
|
||||||
with_definition(config, in_data, buf)?;
|
with_definition(config, in_data, buf)?;
|
||||||
|
|
||||||
write!(buf, "#else{}", config.line_ending).unwrap();
|
write!(buf, "#else{}", config.line_ending).unwrap();
|
||||||
|
|
||||||
with_includes(config, buf);
|
with_includes(config, buf);
|
||||||
|
write!(
|
||||||
|
buf,
|
||||||
|
"{}{}",
|
||||||
|
length_define(config, length),
|
||||||
|
config.line_ending
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
with_declaration(config, buf);
|
with_declaration(config, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,21 +177,8 @@ pub fn with_definition(
|
|||||||
in_data: &[u8],
|
in_data: &[u8],
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
) -> Result<(), HeaderGenerationError> {
|
) -> Result<(), HeaderGenerationError> {
|
||||||
let length: usize = match config.container_type {
|
|
||||||
ContainerType::CString => in_data.len() + 1, // +1 for NUL terminator
|
|
||||||
_ => in_data.len(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let modifiers = definition_modifiers(config);
|
let modifiers = definition_modifiers(config);
|
||||||
|
|
||||||
write!(
|
|
||||||
buf,
|
|
||||||
"{}{}",
|
|
||||||
length_define(config, length),
|
|
||||||
config.line_ending
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
buf,
|
buf,
|
||||||
"{}{} = {};{}",
|
"{}{} = {};{}",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user