1

I have a library that defines a function as follows:

int MAG_robustReadMagModels(char *filename, MAGtype_MagneticModel *(*magneticmodels)[], int array_size)

The library was written in C. I am attempting to use it in C++ like this:

MAGtype_MagneticModel* Models[1];
MAG_robustReadMagModels(filePathNative, &Models, 1);

Which is the way it is used in the example programs. However I get the message

Error   C2664   'int MAG_robustReadMagModels(char *,MAGtype_MagneticModel *(*)[],int)': cannot convert argument 2 from 'MAGtype_MagneticModel *(*)[1]' to 'MAGtype_MagneticModel *(*)[]'    

Both when I attempt to compile it and during code-time.

furthermore, i have not been able to dynamically allocate an unsized array or cast a double pointer to the required type of *(*)[] I'm guessing this is a language incompatibility between C and C++. How do I get around this?

Benjamin
  • 921
  • 5
  • 15
  • Try using `reinterpret_cast<>()` it will remove the error. Hence it will be now `MAG_robustReadMagModels(filePathNative, reinterpret_cast(&Models), 1);` – Alexandru Barbarosie May 27 '15 at 00:29
  • This stackoverflow discusses the differences between reinterpret_cast<> and static_cast<> http://stackoverflow.com/questions/573294/when-to-use-reinterpret-cast as does this stackoverflow http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used – Richard Chambers May 27 '15 at 00:44

1 Answers1

0

I expect that some compilers will be more or less strict about this.

The simplest thing I found was to just use a C style cast.

The following compiles for me with Visual Studio 2005.

MAG_robustReadMagModels(filePathNative, (MAGtype_MagneticModel *(*)[]) &Models, 1);

When I remove the C style cast and just use &Models, I get a compiler error of:

error C2664: 'MAG_robustReadMagModels' : cannot convert parameter 2 from 'MAGtype_MagneticModel *(*__w64 )[1]' to 'MAGtype_MagneticModel *(*)[]'

See also this stackoverflow discussion on C style cast.

This stackoverflow discussion on Performance hit from C++ style casts compares and contrasts C++ style casts with C style casts.

And this stackoverflow discussion on Is it possible to completely avoid C-style casts in C++ has some interesting points about the differences.

Community
  • 1
  • 1
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
  • The most confusing thing is that clang accepts `MAGtype_MagneticModel *(*magneticmodels)[]` as a function parameter, which is clearly a [bug reported back in 2010](https://llvm.org/bugs/show_bug.cgi?id=7468), as [such declarations are illegal in C++ but legal in C](http://stackoverflow.com/questions/6936254/why-is-functionchar-array-a-valid-function-definition-but-not-char-arra) – vsoftco May 27 '15 at 00:52
  • @vsoftco, the problem with C style casts is you are basically telling the compiler that you know more about what is needed than the compiler and I have never felt comfortable about doing that. I would want to do a check to make sure that the data is being passed to the function correctly. – Richard Chambers May 27 '15 at 01:00
  • If the type of the parameter is simply `MAGtype_MagneticModel**` instead of `MAGtype_MagneticModel *(*)[]` (which should be illegal in C++), then passing `Models[0]` should work, see a simple example [here](http://ideone.com/Fs4LLK). – vsoftco May 27 '15 at 01:09
  • @vsoftco, I think if you use `Models[0]` you are passing the first element of the array `Models` which is different from passing a pointer to the first element of the array as in `Models` (without the subscript). I assume you want the entire array and not just the first element. – Richard Chambers May 27 '15 at 01:14
  • In this case, `Models[0]` is the dereferenced pointer, but because it points to an array of fixed size, it will decay to a pointer to the first element. At least that's what I believe it happens (and seems to be confirmed by the live example). – vsoftco May 27 '15 at 01:16
  • @vsoftco, there is a difference between `Models[0]` which passes a copy of the first element of the array and `Models + 0` which passes a copy of a pointer to the first element of the array. `Models[0]` and `*(Models + 0)` are the same and are not the same as `Models + 0`. I did an example using a `struct` as a replacement for `MAGtype_MagneticModel` which would seem to better approximate what the question is about. – Richard Chambers May 27 '15 at 01:36
  • Since I was intrigued by the whole issue, I tested this: http://ideone.com/bEvZpM So I disagree, you pass (via a decay) the pointer to the first element. Let me know if I'm missing something, as I'd also like to get this straight :) – vsoftco May 27 '15 at 01:44
  • This appears to work, but I've opted to go with simply rewriting the offending function to accept a triple pointer (pointer to an array of pointers). @vsoftco, the expression (MAGtype_MagneticModel *(*)[]) is not equivelent to a ** but a ***, so your program doesn't quite match what is being discussed. – Benjamin Jun 22 '15 at 23:28