I am working on a C++ library that shall do image processing. My approach now is to pass two strings to C++ from swift. One string is the path to the image and the second is the output directory.
All the time I get that the file does not exist. How can I get the correct path the asset? The image lies in a directory I have created on my own and is called "test.jpg". I also have a "test2.jpg" in Assets. Have not managed to find that either.
Swift Code:
func getGrayImage() -> Image {
if var resourcePath = Bundle.main.url(forResource: "test", withExtension: "jpg") {
let dir = resourcePath.deletingLastPathComponent()
VideoProcessingWrapper().rgb2gray(resourcePath.absoluteString, dir.absoluteString)
}
return Image("test2")
}
C++ Code:
void VideoProcessing::rgb2gray(const std::string& image_path, const std::string& dir) {
std::cout << "C++: " << std::endl;
std::cout << image_path << std::endl;
std::cout << std::endl;
std::cout << dir << std::endl;
std::cout << "In directory: " <<std::endl;
for (const auto& entry : std::filesystem::directory_iterator(dir)) {
std::cout << entry.path() << std::endl;
}
if (std::filesystem::exists(image_path)) {
std::cout << "File exists" << std::endl;
} else {
std::cout << "File does NOT exist" << std::endl;
return;
}
cv::imread(image_path, cv::IMREAD_COLOR);
}
It even crashes when trying to display all files in the directory, stating that the directory does not exist. But what have I then been given from Bundle.main.url
-call?
This is the printout from the C++ function using a simulator:
C++:
file:///Users/name/Library/Developer/CoreSimulator/Devices/7F438661-8BF5-4A60-B41F-1D4B7FEC6A8E/data/Containers/Bundle/Application/AB3EFF3E-79A4-469C-A3BF-ABDD31A09E61/TestVideoProcess.app/test.jpg
file:///Users/name/Library/Developer/CoreSimulator/Devices/7F438661-8BF5-4A60-B41F-1D4B7FEC6A8E/data/Containers/Bundle/Application/AB3EFF3E-79A4-469C-A3BF-ABDD31A09E61/TestVideoProcess.app/
I get the same behaviour when running on a real iPhone.
2
Answers
The problem here is that
Foundation
framework represents paths with URI‘s, while C++ standard library filesystem relies on more file-path-specific format which may consist of only the following components:A URI consists of quite a lot of different parts:
In this case you need the
path
part only. One trick you can employ here is to build the path frompathComponents
of theURL
instance:Alternatively, as suggested by mani in the comments to your question, you can use the
path
property of the same class, however the documentation says that it also may include parameter string and for some reason it’s now deprecated.No matter what you do, the bundle directory is inside your application and you have no write access to it.