Skip to content

Commit b8806d3

Browse files
committed
mex: windows_shortname()
1 parent 85e4242 commit b8806d3

File tree

6 files changed

+87
-3
lines changed

6 files changed

+87
-3
lines changed

+stdlib/windows_shortname.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
p (1,1) string
1212
end
1313

14-
s = string.empty;
14+
s = "";
1515

1616
if ~ispc || stdlib.is_url(p)
1717
return

private/get_mex_sources.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
fullfile(top, "src/set_permissions.cpp"), ...
1111
};
1212

13+
s = fullfile(top, "src/windows_shortname.cpp");
14+
if ispc
15+
s(end+1) = fullfile(top, "src/windows.cpp");
16+
end
17+
srcs{end+1} = s;
18+
19+
1320
% isSymbolicLink() new in R2024b
1421
if ~isMATLABReleaseOlderThan("R2024b")
1522

src/win32_fs.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
bool fs_win32_is_symlink(std::string path);
1+
#include <string>
2+
3+
bool fs_win32_is_symlink(std::string);
4+
5+
std::string fs_shortname(std::string);

src/windows.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <string>
22
#include <cstddef>
3+
#include <cstdlib> // for _MAX_PATH
34

45
#define WIN32_LEAN_AND_MEAN
56
#include <windows.h>
@@ -118,3 +119,20 @@ bool fs_win32_is_symlink(std::string path)
118119
(reparseTag == IO_REPARSE_TAG_MOUNT_POINT);
119120

120121
}
122+
123+
124+
std::string fs_shortname(std::string in)
125+
{
126+
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getshortpathnamew
127+
// the path must exist
128+
129+
std::string out(_MAX_PATH, '\0');
130+
// size does not include null terminator
131+
if(auto L = GetShortPathNameA(in.data(), out.data(), static_cast<DWORD>(out.size()));
132+
L > 0 && L < out.length()){
133+
out.resize(L);
134+
return out;
135+
}
136+
137+
return {};
138+
}

src/windows_shortname.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// C++ Matlab MEX function using C++17 <filesystem>
2+
// https://www.mathworks.com/help/matlab/matlab_external/data-types-for-passing-mex-function-data-1.html
3+
4+
#include "mex.hpp"
5+
#include "mexAdapter.hpp"
6+
7+
#include <string>
8+
// note: <string_view> causes compile failures with MSVC at least
9+
10+
#include <vector>
11+
#include <memory>
12+
13+
#if defined(_WIN32)
14+
#include "win32_fs.h"
15+
#endif
16+
17+
18+
class MexFunction : public matlab::mex::Function {
19+
public:
20+
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
21+
// boilerplate engine & ArrayFactory setup
22+
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
23+
24+
matlab::data::ArrayFactory factory;
25+
// boilerplate input checks
26+
if (inputs.size() != 1) {
27+
matlabPtr->feval(u"error", 0,
28+
std::vector<matlab::data::Array>({ factory.createScalar("One input required") }));
29+
}
30+
if (inputs[0].getType() != matlab::data::ArrayType::MATLAB_STRING) {
31+
matlabPtr->feval(u"error", 0,
32+
std::vector<matlab::data::Array>({ factory.createScalar("Input must be a string") }));
33+
}
34+
if (inputs[0].getNumberOfElements() != 1) {
35+
matlabPtr->feval(u"error", 0,
36+
std::vector<matlab::data::Array>({ factory.createScalar("Input must be a scalar string") }));
37+
}
38+
39+
// Matlab strings are an array, so we use [0][0] to get the first element
40+
std::string inputStr = inputs[0][0];
41+
42+
// actual function algorithm / computation
43+
#if defined(_WIN32)
44+
std::string s = fs_shortname(inputStr);
45+
#else
46+
std::string s = "";
47+
#endif
48+
49+
// convert to Matlab output -- even scalars are arrays in Matlab
50+
// https://www.mathworks.com/help/matlab/matlab_external/create-matlab-array-with-matlab-data-cpp-api.html
51+
// https://www.mathworks.com/help/matlab/apiref/matlab.data.arrayfactory.html
52+
53+
outputs[0] = factory.createScalar(s);
54+
}
55+
};

test/TestWindowsCOM.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
methods (Test)
88

99
function test_not(tc, Pn)
10-
tc.verifyEmpty(stdlib.windows_shortname(Pn))
10+
tc.verifyEqual(stdlib.windows_shortname(Pn), "")
1111
end
1212

1313
function test_short_folder(tc)

0 commit comments

Comments
 (0)