Using coder.ceval to getcwd()

7 views (last 30 days)
Michael
Michael on 3 Nov 2022
Commented: Michael on 5 Nov 2022
I am trying to get the current working directory in generated C++ code. I think it is possible using coder.ceval() by calling the getcwd() C function. My primary question is how to implement this. I have tried for a while to get this to work but I am stuck. I have read over the documentation for both getcwd() and coder.ceval() and tried the following code.
function [] = uavrt_detection_debug()
%#codegen
fprintf('Program started\n')
%Get current working directory
if coder.target('MATLAB')
curr_dir = pwd;
else
%Initialize a long path
curr_dir = ['basic_path/basic_path/basic_path/basic_path/basic_path/basic_path/basic_path/basic_path/basic_path/',char(0)];%Add c string termination character
coder.updateBuildInfo('addIncludePaths','/Library/Developer/CommandLineTools/SDKs/MacOSX12.3.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/sys/unistd.h');
coder.cinclude('unistd.h');
y = coder.opaque('size_t','200');
coder.ceval('getcwd',curr_dir, y);
end
fprintf('Curr Directory is: %s',curr_dir)
end
The code I use for code deployment on my remote Linux machine is shown at the end of this question. When I deploy this and try running the program (ie. $ros2 run uavrt_detection_debug uavrt_detection_debug) on my target machine, I get:
Program started
*** buffer overflow detected ***: terminated
It looks like there is an issue with where or how much getcwd() is writing.
In reviewing the output from the code generation in the Matlab command window (shown below in the 'Output from Code Generation' section), there are warnings but the code generation is successful. It looks like getcwd() is receiving the memory location of curr_dir: &curr_dir[0]. The documentation for getcwd() says it requires a reference:
char *getcwd(char *buffer, size_t size);
I have also tried passing coder.ref(curr_dir) as the first argument to coder.eval but I see the same in my code generation ouput (&curr_dir[0]). I've also tried setting the size of the curr_dir to 202 bytes to account for the c-string termination character. I don't think I care about the warnings about the output, although it would be nice to be able to recover the output char from getcwd() in order to recover from program errors.
Note that I originally posed a similar question here, but am only now getting around to trying the solution proposed by Walter Roberson.
Thanks.
Output from Code Generation
The output at the Matlab command window when run code generation is the following:
Connecting to ROS 2 device at 'XXX.XXX.XXX.XXX'.
Using ROS 2 workspace '~/uavrt_ws' to build ROS 2 node.
---
Transferring generated code for 'uavrt_detection_debug' to ROS device.
Starting build for ROS node.
---
ROS 2 project directory: /home/dasl/uavrt_ws/src
Starting >>> uavrt_detection_debug
--- stderr: uavrt_detection_debug
/home/dasl/uavrt_ws/src/uavrt_detection_debug/src/uavrt_detection_debug.cpp: In function 'void uavrt_detection_debug()':
/home/dasl/uavrt_ws/src/uavrt_detection_debug/src/uavrt_detection_debug.cpp:43:9: warning: ignoring return value of 'char* getcwd(char*, size_t)', declared with attribute warn_unused_result [-Wunused-result]
43 | getcwd(&curr_dir[0], 200);
| ~~~~~~^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/unistd.h:1166,
from /home/dasl/uavrt_ws/src/uavrt_detection_debug/src/uavrt_detection_debug.cpp:13:
In function 'char* getcwd(char*, size_t)',
inlined from 'void uavrt_detection_debug()' at /home/dasl/uavrt_ws/src/uavrt_detection_debug/src/uavrt_detection_debug.cpp:43:9:
/usr/include/x86_64-linux-gnu/bits/unistd.h:208:27: warning: call to '__getcwd_chk_warn' declared with attribute warning: getcwd caller with bigger length than size of destination buffer [-Wattribute-warning]
208 | return __getcwd_chk_warn (__buf, __size, __bos (__buf));
| ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/dasl/uavrt_ws/src/uavrt_detection_debug/src/main.cpp: In function 'void threadFunction()':
/home/dasl/uavrt_ws/src/uavrt_detection_debug/src/main.cpp:21:33: warning: catching polymorphic type 'class std::runtime_error' by value [-Wcatch-value=]
21 | } catch (std::runtime_error e) {
| ^
---
Finished <<< uavrt_detection_debug [6.17s]
Summary: 1 package finished [6.53s]
1 package had stderr output: uavrt_detection_debug
Code generation successful.
Code Generation Script
clear
%% Remote ROS2 BUILDING
cfg = coder.config('exe');
cfg.Hardware = coder.hardware('Robot Operating System 2 (ROS 2)');
%cfg.Hardware.BuildAction = 'Build and run';
cfg.Hardware.BuildAction = 'Build and load';
cfg.Hardware.RemoteDeviceAddress = 'XXX.XXX.XXX.XXX';
cfg.Hardware.RemoteDeviceUsername = 'XXXX';
cfg.Hardware.RemoteDevicePassword = 'XXXX';
cfg.Hardware.DeployTo = 'Remote Device';
cfg.Hardware.ROS2Folder = '/opt/ros/galactic';
cfg.Hardware.ROS2Workspace = '~/uavrt_ws';
cfg.HardwareImplementation.ProdHWDeviceType = 'Intel->x86-64 (Linux 64)';
cfg.RuntimeChecks = true;%Disable for final deployments.
codegen uavrt_detection_debug -args {} -config cfg
  2 Comments
Michael
Michael on 3 Nov 2022
Okay. Thanks for the clarification.

Sign in to comment.

Accepted Answer

Matan Silver
Matan Silver on 3 Nov 2022
Edited: Matan Silver on 3 Nov 2022
Hello Michael,
I've written the following function which gets the current directory in generated code:
function currentDir = getCWD()
if coder.target("MATLAB")
currentDir = pwd;
else
coder.cinclude('unistd.h');
bufferTemplate = repmat('c', 1, 200);
untokenizedDir = coder.nullcopy(bufferTemplate);
coder.ceval('getcwd', coder.ref(untokenizedDir), 200);
currentDir = strtok(untokenizedDir, char(0));
end
end
And ran codegen and the MEX with the following script:
codegen -config:mex ./getCWD.m
getCWD
getCWD_mex
The generated code seems to compile and run fine on my host machine:
>> doit
Code generation successful.
ans =
'/tmp/tmp.LxTn2ol9SY'
ans =
'/tmp/tmp.LxTn2ol9SY'
And the generated code contains:
char_T untokenizedDir[200];
(void)sp;
getcwd(&untokenizedDir[0], 200.0);
I haven't tested this with any other target hardware or with ROS, but it looks like this works at least on the host machine. Does this work for you?
  9 Comments
Michael
Michael on 5 Nov 2022
That did it! Thanks so much for then help on this issue!

Sign in to comment.

More Answers (0)

Categories

Find more on Deployment, Integration, and Supported Hardware in Help Center and File Exchange

Products


Release

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!