0

I know there are many SO questions related to this, but none of the ones I've come across solve my problem. So here goes.

I have a C++ file and method:

MyClass.cpp

extern "C" {
#include "C_methods.h"
}

void MyClass::run_c_method_1()
{
    std::string filename_1 = <from somewhere else>;
    std::string filename_2 = <from somewhere else>;
    c_method_1(filename_1.c_str(), filename_2.c_str());
}

C_methods.h

#ifndef Project_C_methods_h
#define Project_C_methods_h

int c_method_1(char* filename1, char* filename_2);

#endif

C_methods.c

#include "C_methods.h"

int c_method_1(char* filename1, char* filename_2) {
  /* Do some stuff */
  return 0;
}

I'm building/running this on OSX in Xcode, and the compiler is telling me:

No matching function call to 'c_method_1'.

To me, this makes no sense. From other SO answers, it looks like the extern I've wrapped the header #include "C_methods.h" in should tell the compiler that those functions are present, and to be compiled in C.

Does anyone have any idea where I could be going wrong here? I'm stumped.

Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
Brett
  • 11,637
  • 34
  • 127
  • 213

2 Answers2

2

Your problem can actually be simplified to this:

#include <string>

void foo(char *);

int main() {
    std::string s;
    foo(s.c_str());
}

The function takes a char *, but a const char * is passed to it. If the function does not modify the pointee, it should take a const char *. Otherwise, you'll have to use a modifiable buffer. As of C++11, std::string's &s[0] counts as one up until just before the internal null character at the end. Before that, you're better off with std::vector<char>.

chris
  • 60,560
  • 13
  • 143
  • 205
0

If a legacy function takes a non-const pointer but you know it WON'T modify the data (common in old C code), then it's permissible to use, in this case, const_cast<char *>(s.c_str()). If the function does modify the data, it's undefined behavior!

If the function might modify the data then you need to copy your string into a modifiable buffer and pass a pointer to that instead.

string s;
vector<char> buffer(s.size() + 1); // prepare buffer, with space for null char
strcpy(buffer.data(), s.c_str()); // copy string data
foo(buffer.data());
s = buffer.data(); // copy back string data if required
Neil Kirk
  • 21,327
  • 9
  • 53
  • 91