Skip to content

Commit c5fdc8e

Browse files
GH-38369: [MATLAB] Create utility functions for simplifying management of Proxy instances for Arrays (#46907)
### Rationale for this change This is a follow up to #38357 (comment). In the C++ code for the MATLAB interface, we frequently `wrap`/`unwrap` Arrow types, like `arrow::Array`, into/from a corresponding `libmexclass` `Proxy` objects. This currently takes several lines of code, leading to lots of code duplication and introduces room for subtle implementation errors. It would be helpful to abstract away some of the steps involved in `Proxy` creation/management into a set of helper utilities that we can reuse in the C++ code for the MATLAB interface. ### What changes are included in this PR? 1. Added a new utility function that wraps a `std::shared_ptr<arrow::Array>` in a `std::shared_ptr<arrow::matlab::array::proxy::Array>`. Its function signature is ```c++ arrow::Result<std::shared_ptr<arrow::matlab::array::proxy::Array>> wrap(const std::shared_ptr<arrow::Array>& array);` ```` 2. Added a new utility function that wraps a `std::shared_ptr<arrow::Array>` in a `std::shared_ptr<arrow::matlab::array::proxy::Array>` and adds the proxy to the `libmexclass::proxy::ProxyManager`. Its function signature is ```c++ arrow::Result<std::shared_ptr<arrow::matlab::array::proxy::Array>> wrap_and_manage(const std::shared_ptr<arrow::Array>& array); ``` 3. Added a new utility function that wraps a `std::shared_ptr<arrow::DataType>` in a `std::shared_ptr<arrow::matlab::type::proxy::Type>`. Its function signature is ```c++ arrow::Result<std::shared_ptr<arrow::matlab::type::proxy::Type>> wrap(const std::shared_ptr<arrow::DataType>& type); ``` 4. Added a new utility function that wraps a `std::shared_ptr<arrow::DataType>` in a `std::shared_ptr<arrow::matlab::type::proxy::DataType>` and adds the proxy to the `libmexclass::proxy::ProxyManager`. It's function signature is ```c++ arrow::Result<std::shared_ptr<arrow::matlab::type::proxy::Type>> wrap_and_manage(const std::shared_ptr<arrow::DataType>& type); ``` 5. Deleted `arrow::matlab::array::proxy::wrap` and `arrow::matlab::type::proxy::wrap` functions. ### Are these changes tested? Tested via the existing MATLAB test classes. ### Are there any user-facing changes? No. * GitHub Issue: #38369 Lead-authored-by: Sarah Gilmore <sgilmore@mathworks.com> Co-authored-by: Sarah Gilmore <74676073+sgilmore10@users.noreply.github.com> Co-authored-by: Kevin Gurney <kevin.p.gurney@gmail.com> Signed-off-by: Sarah Gilmore <sgilmore@mathworks.com>
1 parent d97e7ab commit c5fdc8e

19 files changed

Lines changed: 330 additions & 437 deletions

File tree

matlab/src/cpp/arrow/matlab/array/proxy/array.cc

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@
1919
#include "arrow/util/utf8.h"
2020

2121
#include "arrow/matlab/array/proxy/array.h"
22-
#include "arrow/matlab/array/proxy/wrap.h"
2322
#include "arrow/matlab/bit/unpack.h"
2423
#include "arrow/matlab/error/error.h"
2524
#include "arrow/matlab/index/validate.h"
26-
#include "arrow/matlab/type/proxy/wrap.h"
25+
#include "arrow/matlab/proxy/wrap.h"
2726
#include "arrow/pretty_print.h"
2827
#include "arrow/type_traits.h"
2928

@@ -110,20 +109,9 @@ void Array::getValid(libmexclass::proxy::method::Context& context) {
110109
}
111110

112111
void Array::getType(libmexclass::proxy::method::Context& context) {
113-
namespace mda = ::matlab::data;
114-
115-
mda::ArrayFactory factory;
116-
117-
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto type_proxy, type::proxy::wrap(array->type()),
118-
context, error::ARRAY_FAILED_TO_CREATE_TYPE_PROXY);
119-
120-
const auto type_id = static_cast<int32_t>(type_proxy->unwrap()->id());
121-
const auto proxy_id = libmexclass::proxy::ProxyManager::manageProxy(type_proxy);
122-
123-
mda::StructArray output = factory.createStructArray({1, 1}, {"ProxyID", "TypeID"});
124-
output[0]["ProxyID"] = factory.createScalar(proxy_id);
125-
output[0]["TypeID"] = factory.createScalar(type_id);
126-
context.outputs[0] = output;
112+
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(
113+
context.outputs[0], arrow::matlab::proxy::wrap_and_manage(array->type()), context,
114+
error::ARRAY_FAILED_TO_CREATE_TYPE_PROXY);
127115
}
128116

129117
void Array::isEqual(libmexclass::proxy::method::Context& context) {
@@ -167,18 +155,9 @@ void Array::slice(libmexclass::proxy::method::Context& context) {
167155
context, error::ARRAY_SLICE_NEGATIVE_LENGTH);
168156

169157
auto sliced_array = array->Slice(offset, length);
170-
const auto type_id = static_cast<int32_t>(sliced_array->type_id());
171-
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto sliced_array_proxy,
172-
array::proxy::wrap(sliced_array), context,
173-
error::ARRAY_SLICE_FAILED_TO_CREATE_ARRAY_PROXY);
174-
175-
const auto proxy_id = libmexclass::proxy::ProxyManager::manageProxy(sliced_array_proxy);
176-
177-
mda::ArrayFactory factory;
178-
mda::StructArray output = factory.createStructArray({1, 1}, {"ProxyID", "TypeID"});
179-
output[0]["ProxyID"] = factory.createScalar(proxy_id);
180-
output[0]["TypeID"] = factory.createScalar(type_id);
181-
context.outputs[0] = output;
158+
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(
159+
context.outputs[0], arrow::matlab::proxy::wrap_and_manage(sliced_array), context,
160+
error::ARRAY_SLICE_FAILED_TO_CREATE_ARRAY_PROXY);
182161
}
183162

184163
void Array::exportToC(libmexclass::proxy::method::Context& context) {

matlab/src/cpp/arrow/matlab/array/proxy/chunked_array.cc

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@
1919

2020
#include "arrow/matlab/array/proxy/array.h"
2121
#include "arrow/matlab/array/proxy/chunked_array.h"
22-
#include "arrow/matlab/array/proxy/wrap.h"
2322
#include "arrow/matlab/error/error.h"
24-
#include "arrow/matlab/type/proxy/wrap.h"
23+
#include "arrow/matlab/proxy/wrap.h"
2524

2625
#include "libmexclass/proxy/ProxyManager.h"
2726

@@ -126,35 +125,15 @@ void ChunkedArray::getChunk(libmexclass::proxy::method::Context& context) {
126125
}
127126

128127
const auto array = chunked_array->chunk(index);
129-
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto array_proxy,
130-
arrow::matlab::array::proxy::wrap(array), context,
131-
error::UNKNOWN_PROXY_FOR_ARRAY_TYPE);
132-
133-
const auto array_proxy_id = libmexclass::proxy::ProxyManager::manageProxy(array_proxy);
134-
const auto type_id = static_cast<int64_t>(array->type_id());
135-
136-
mda::StructArray output = factory.createStructArray({1, 1}, {"ProxyID", "TypeID"});
137-
output[0]["ProxyID"] = factory.createScalar(array_proxy_id);
138-
output[0]["TypeID"] = factory.createScalar(type_id);
139-
context.outputs[0] = output;
128+
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(context.outputs[0],
129+
arrow::matlab::proxy::wrap_and_manage(array),
130+
context, error::UNKNOWN_PROXY_FOR_ARRAY_TYPE);
140131
}
141132

142133
void ChunkedArray::getType(libmexclass::proxy::method::Context& context) {
143-
namespace mda = ::matlab::data;
144-
145-
mda::ArrayFactory factory;
146-
147-
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto type_proxy,
148-
type::proxy::wrap(chunked_array->type()), context,
149-
error::ARRAY_FAILED_TO_CREATE_TYPE_PROXY);
150-
151-
const auto proxy_id = libmexclass::proxy::ProxyManager::manageProxy(type_proxy);
152-
const auto type_id = static_cast<int32_t>(type_proxy->unwrap()->id());
153-
154-
mda::StructArray output = factory.createStructArray({1, 1}, {"ProxyID", "TypeID"});
155-
output[0]["ProxyID"] = factory.createScalar(proxy_id);
156-
output[0]["TypeID"] = factory.createScalar(type_id);
157-
context.outputs[0] = output;
134+
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(
135+
context.outputs[0], arrow::matlab::proxy::wrap_and_manage(chunked_array->type()),
136+
context, error::ARRAY_FAILED_TO_CREATE_TYPE_PROXY);
158137
}
159138

160139
void ChunkedArray::isEqual(libmexclass::proxy::method::Context& context) {

matlab/src/cpp/arrow/matlab/array/proxy/list_array.cc

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717

1818
#include "arrow/matlab/array/proxy/list_array.h"
1919
#include "arrow/matlab/array/proxy/numeric_array.h"
20-
#include "arrow/matlab/array/proxy/wrap.h"
2120
#include "arrow/matlab/array/validation_mode.h"
2221
#include "arrow/matlab/error/error.h"
22+
#include "arrow/matlab/proxy/wrap.h"
23+
2324
#include "libmexclass/proxy/ProxyManager.h"
2425

2526
namespace arrow::matlab::array::proxy {
@@ -78,20 +79,9 @@ void ListArray::getValues(libmexclass::proxy::method::Context& context) {
7879
auto list_array = std::static_pointer_cast<arrow::ListArray>(array);
7980
auto value_array = list_array->values();
8081

81-
// Wrap the array within a proxy object if possible.
82-
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto value_array_proxy, proxy::wrap(value_array),
82+
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(context.outputs[0],
83+
arrow::matlab::proxy::wrap_and_manage(value_array),
8384
context, error::UNKNOWN_PROXY_FOR_ARRAY_TYPE);
84-
const auto value_array_proxy_id = ProxyManager::manageProxy(value_array_proxy);
85-
const auto type_id = value_array->type_id();
86-
87-
// Return a struct with two fields: ProxyID and TypeID. The MATLAB
88-
// layer will use these values to construct the appropriate MATLAB
89-
// arrow.array.Array subclass.
90-
mda::ArrayFactory factory;
91-
mda::StructArray output = factory.createStructArray({1, 1}, {"ProxyID", "TypeID"});
92-
output[0]["ProxyID"] = factory.createScalar(value_array_proxy_id);
93-
output[0]["TypeID"] = factory.createScalar(static_cast<int32_t>(type_id));
94-
context.outputs[0] = output;
9585
}
9686

9787
void ListArray::getOffsets(libmexclass::proxy::method::Context& context) {

matlab/src/cpp/arrow/matlab/array/proxy/struct_array.cc

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616
// under the License.
1717

1818
#include "arrow/matlab/array/proxy/struct_array.h"
19-
#include "arrow/matlab/array/proxy/wrap.h"
2019
#include "arrow/matlab/bit/pack.h"
2120
#include "arrow/matlab/error/error.h"
2221
#include "arrow/matlab/index/validate.h"
23-
22+
#include "arrow/matlab/proxy/wrap.h"
2423
#include "arrow/util/utf8.h"
2524

2625
#include "libmexclass/proxy/ProxyManager.h"
@@ -114,21 +113,9 @@ void StructArray::getFieldByIndex(libmexclass::proxy::method::Context& context)
114113
const int32_t index = matlab_index - 1;
115114

116115
auto field_array = struct_array->field(index);
117-
118-
// Wrap the array within a proxy object if possible.
119-
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto field_array_proxy, proxy::wrap(field_array),
116+
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(context.outputs[0],
117+
arrow::matlab::proxy::wrap_and_manage(field_array),
120118
context, error::UNKNOWN_PROXY_FOR_ARRAY_TYPE);
121-
const auto field_array_proxy_id = ProxyManager::manageProxy(field_array_proxy);
122-
const auto type_id = field_array->type_id();
123-
124-
// Return a struct with two fields: ProxyID and TypeID. The MATLAB
125-
// layer will use these values to construct the appropriate MATLAB
126-
// arrow.array.Array subclass.
127-
mda::ArrayFactory factory;
128-
mda::StructArray output = factory.createStructArray({1, 1}, {"ProxyID", "TypeID"});
129-
output[0]["ProxyID"] = factory.createScalar(field_array_proxy_id);
130-
output[0]["TypeID"] = factory.createScalar(static_cast<int32_t>(type_id));
131-
context.outputs[0] = output;
132119
}
133120

134121
void StructArray::getFieldByName(libmexclass::proxy::method::Context& context) {
@@ -154,19 +141,9 @@ void StructArray::getFieldByName(libmexclass::proxy::method::Context& context) {
154141
}
155142

156143
// Wrap the array within a proxy object if possible.
157-
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto field_array_proxy, proxy::wrap(field_array),
144+
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(context.outputs[0],
145+
arrow::matlab::proxy::wrap_and_manage(field_array),
158146
context, error::UNKNOWN_PROXY_FOR_ARRAY_TYPE);
159-
const auto field_array_proxy_id = ProxyManager::manageProxy(field_array_proxy);
160-
const auto type_id = field_array->type_id();
161-
162-
// Return a struct with two fields: ProxyID and TypeID. The MATLAB
163-
// layer will use these values to construct the appropriate MATLAB
164-
// arrow.array.Array subclass.
165-
mda::ArrayFactory factory;
166-
mda::StructArray output = factory.createStructArray({1, 1}, {"ProxyID", "TypeID"});
167-
output[0]["ProxyID"] = factory.createScalar(field_array_proxy_id);
168-
output[0]["TypeID"] = factory.createScalar(static_cast<int32_t>(type_id));
169-
context.outputs[0] = output;
170147
}
171148

172149
void StructArray::getFieldNames(libmexclass::proxy::method::Context& context) {

matlab/src/cpp/arrow/matlab/array/proxy/wrap.cc

Lines changed: 0 additions & 94 deletions
This file was deleted.

matlab/src/cpp/arrow/matlab/array/proxy/wrap.h

Lines changed: 0 additions & 30 deletions
This file was deleted.

matlab/src/cpp/arrow/matlab/c/proxy/array_importer.cc

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@
1818
#include "arrow/array.h"
1919
#include "arrow/c/bridge.h"
2020

21-
#include "arrow/matlab/array/proxy/wrap.h"
2221
#include "arrow/matlab/c/proxy/array_importer.h"
2322
#include "arrow/matlab/error/error.h"
24-
25-
#include "libmexclass/proxy/ProxyManager.h"
23+
#include "arrow/matlab/proxy/wrap.h"
2624

2725
namespace arrow::matlab::c::proxy {
2826

@@ -35,7 +33,6 @@ libmexclass::proxy::MakeResult ArrayImporter::make(
3533

3634
void ArrayImporter::import(libmexclass::proxy::method::Context& context) {
3735
namespace mda = ::matlab::data;
38-
using namespace libmexclass::proxy;
3936

4037
mda::StructArray args = context.inputs[0];
4138
const mda::TypedArray<uint64_t> arrow_array_address_mda = args[0]["ArrowArrayAddress"];
@@ -52,18 +49,9 @@ void ArrayImporter::import(libmexclass::proxy::method::Context& context) {
5249
arrow::ImportArray(arrow_array, arrow_schema),
5350
context, error::C_IMPORT_FAILED);
5451

55-
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto array_proxy,
56-
arrow::matlab::array::proxy::wrap(array), context,
57-
error::UNKNOWN_PROXY_FOR_ARRAY_TYPE);
58-
59-
mda::ArrayFactory factory;
60-
const auto array_proxy_id = ProxyManager::manageProxy(array_proxy);
61-
const auto array_proxy_id_mda = factory.createScalar(array_proxy_id);
62-
const auto array_type_id_mda =
63-
factory.createScalar(static_cast<int32_t>(array->type_id()));
64-
65-
context.outputs[0] = array_proxy_id_mda;
66-
context.outputs[1] = array_type_id_mda;
52+
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(context.outputs[0],
53+
arrow::matlab::proxy::wrap_and_manage(array),
54+
context, error::UNKNOWN_PROXY_FOR_ARRAY_TYPE);
6755
}
6856

6957
} // namespace arrow::matlab::c::proxy

0 commit comments

Comments
 (0)