Context: I want to access the address of a C global const variable in Swift.
Here is my simple project:
Package.swift
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "TestApp",
platforms: [.macOS(.v14), .iOS(.v13), .watchOS(.v6)],
products: [
.executable(name: "MyApp", targets: ["MyApp"])
],
targets: [
.executableTarget(name: "MyApp",
dependencies: [
.target(name: "MyCLib")
]
),
.target(name: "MyCLib")
]
)
Sources/MyCLib/my_c_lib.c
#include <stdio.h>
const int hello_value = 2;
void hello_world() {
printf("Hello World from MyCLib (hello_value:0x%p)\n", &hello_value);
}
Sources/MyCLib/include/MyCLib.h
extern const int hello_value;
void hello_world();
Sources/MyApp/main.swift
import MyCLib
withUnsafePointer(to: &hello_value) { helloValuePtr in
print("helloValuePtr: \(helloValuePtr)")
}
Trying the code above I have the error:
% swift run
Building for debugging...
error: emit-module command failed with exit code 1 (use -v to see invocation)
/Users/olivier/dev/test_c_const/Sources/MyApp/main.swift:3:23: error: cannot pass immutable value as inout argument: 'hello_value' is a 'let' constant
withUnsafePointer(to: &hello_value) { helloValuePtr in
^~~~~~~~~~~~
/Users/olivier/dev/test_c_const/Sources/MyApp/main.swift:3:23: error: cannot pass immutable value as inout argument: 'hello_value' is a 'let' constant
withUnsafePointer(to: &hello_value) { helloValuePtr in
^~~~~~~~~~~~
error: fatalError
- Changing the code such as:
import MyCLib
hello_world()
withUnsafePointer(to: hello_value) { helloValuePtr in
print("helloValuePtr: \(helloValuePtr)")
}
... it builds but it gaves me the wrong answer:
% swift run
Building for debugging...
[3/3] Linking MyApp
Build complete! (1.26s)
Hello World from MyCLib (hello_value:0x0x101876f84)
helloValuePtr: 0x00007ff7be68c198
I suspect it gives me the address of the swift copy of the C variable hello_world
.
A workaround is obviously to modify the C code to expose the address of the global variable const int* hello_value_ptr = &hello_value;
but this example is only for this post - in the big picture I cannot modify it.