Main Content

Integrate External C++ Code That Uses String Arguments

R2026b

This example shows how to call an external C++ function that uses std::string from MATLAB® code intended for C++ code generation. To use std::string in generated C++ code, you must translate MATLAB character arrays to C++ strings and then translate C++ strings back to MATLAB character arrays. This example demonstrates how to:

Explore the External C++ Code

The external C++ code in this example converts a string to uppercase. It uses helper functions to query the string length and copy the result back to a character array. Examine the C++ header file stringUtils.hpp.

type stringUtils.hpp
#pragma once
#include <string>

void initFromChar(std::string* output, char const* inChar, int length);
void toUpperCase(const std::string* input, std::string* output);
int stringLength(const std::string* str);
void writeToChar(const std::string* str, char* outChar);

The header file declares these C++ functions:

  • initFromChar constructs a std::string from a character pointer and an explicit length. Because MATLAB character arrays are not null-terminated, this function uses the two-argument std::string constructor that accepts a length instead of relying on a null terminator. See Generate C/C++ Strings from MATLAB Strings and Character Row Vectors.

  • toUpperCase accepts a const std::string* input and writes the uppercase result to a std::string* output.

  • stringLength returns the number of characters in a std::string.

  • writeToChar copies the contents of a std::string into a char* buffer so that MATLAB can read it.

The C++ functions accept pointers to the std::string variables so that coder.rref and coder.wref can pass them directly. The functions stringLength and writeToChar are necessary because the code generator cannot directly access data stored inside a std::string object.

Explore the MATLAB Code

Examine the function upperCaseString.

type upperCaseString.m
function result = upperCaseString(inputStr) %#codegen
coder.cinclude("stringUtils.hpp");
coder.updateBuildInfo("addSourceFiles","stringUtils.cpp")

inputCppStr = coder.opaque("std::string","HeaderFile","<string>");
coder.ceval("initFromChar",coder.wref(inputCppStr),coder.rref(inputStr),int32(length(inputStr)));

outputCppStr = coder.opaque("std::string","std::string()","HeaderFile","<string>");
coder.ceval("toUpperCase",coder.rref(inputCppStr),coder.wref(outputCppStr));

outLen = int32(0);
outLen = coder.ceval("stringLength",coder.rref(outputCppStr));

result = blanks(outLen);
coder.ceval("writeToChar",coder.rref(outputCppStr),coder.wref(result));
end

This function performs these steps:

  1. Includes the external source code and header files by using coder.cinclude and coder.updateBuildInfo.

  2. Declares an inputCppStr variable of type std::string by using coder.opaque.

  3. Calls initFromChar by using coder.ceval to construct the std::string from the input character array. The function passes the array by using coder.rref and the length as int32.

  4. Calls the external C++ function toUpperCase by using coder.ceval with coder.rref and coder.wref to pass pointers to the opaque variables.

  5. Calls stringLength with coder.rref to determine the length of the output string.

  6. Allocates a character buffer and copies the output std::string data into it by calling writeToChar with coder.wref.

Generate and Run a MEX Function

Because the MATLAB interpreter does not support code generation functions such as coder.ceval, you cannot test the upperCaseString function in MATLAB. To test this function, generate and run a MEX function.

By default, the codegen command generates a C MEX function in the working folder. Use the -args option to specify that the input argument is a variable-length character vector, and use the -lang:c++ option to generate C++.

codegen -lang:c++ upperCaseString -args {coder.typeof(char('X'),[1 inf])}
Code generation successful.

Test the MEX function with a sample input. The MEX function produces the expected output.

upperCaseString_mex('hello world')
ans = 
'HELLO WORLD'

Generate and Inspect C++ Code

Generate a C++ static library by using the codegen command with the -config:lib and -lang:c++ options. Use the same -args syntax that you used to generate the MEX function.

codegen -config:lib -lang:c++ upperCaseString -args {coder.typeof(char('X'),[1 inf])}
Code generation successful.

Examine the generated function signature.

header_file = fullfile("codegen","lib","upperCaseString","upperCaseString.h");
coder.example.extractLines(header_file,"// Function Declarations","#endif",0,0)
extern void upperCaseString(const coder::array<char, 2U> &inputStr,
                            coder::array<char, 2U> &result);

The generated function accepts a coder::array<char,2U> for the input and returns the result in another coder::array<char,2U>. Internally, the generated code constructs std::string objects and passes them by pointer to the external C++ functions.

Examine the generated function body to see how the std::string variables are used.

cpp_file = fullfile("codegen","lib","upperCaseString","upperCaseString.cpp");
coder.example.extractLines(cpp_file,"void upperCaseString","//",1,0)
void upperCaseString(const coder::array<char, 2U> &inputStr,
                     coder::array<char, 2U> &result)
{
  std::string inputCppStr;
  std::string outputCppStr;
  int n;
  initFromChar(&inputCppStr, &inputStr[0], inputStr.size(1));
  toUpperCase(&inputCppStr, &outputCppStr);
  n = stringLength(&outputCppStr);
  result.set_size(1, n);
  for (int i{0}; i < n; i++) {
    result[i] = ' ';
  }
  writeToChar(&outputCppStr, &result[0]);
}

The generated C++ function:

  • Declares inputCppStr and outputCppStr as std::string variables.

  • Calls initFromChar to construct inputCppStr from the input character array and its length.

  • Passes the std::string variables by pointer to the toUpperCase, stringLength, and writeToChar functions.

See Also

| |

Topics