0

I am thinking this is a later Xcode issue (I am using Xcode 11) as this code was fine previously in older versions.

In my main.mm file I have the following;

int main(int argc, char *argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSString * path = [[NSBundle mainBundle] pathForResource:  @"fd" ofType: @"dat"];
    NSData* image = [NSData dataWithContentsOfFile:path];

    const char* szPathName = [path UTF8String];
    const char* pos = strrchr (szPathName, '/');
    //char* pos = strrchr (szPathName, '/');


    *pos = 0;

    if (CreateFaceFatted(szPathName) == 0)
    {
        NSLog(@"Init Dictionary failed");
    }
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

I have changed the char* pos = strrchr (szPathName, '/'); to const char* pos = strrchr (szPathName, '/'); as otherwise it would throw a

Cannot initialize a variable of type 'char *' with an rvalue of type 'const char *'

so by doing the const char instead, I at least could proceed further, however on the following part;

*pos = 0;

I receive an error Read only variable is not assignable

I have a small understanding of the c++ code mixed with obj-c but I am struggling to figure a way to get this to compile

user1695971
  • 103
  • 1
  • 5
  • 15
  • There are two `std::strrchr` overloads in the C++ standard library: one that takes a `const char*` first argument and returns a `const char*` result, the other that takes a `char *` argument and returns a `char *` result. You're using the former due to the const-ness of `szPathName`. To use the latter `szPathName` needs to be non-const. – WhozCraig May 08 '20 at 10:53

2 Answers2

2

You declared the pointer szPathName as a pointer to constant data

 const char* szPathName = [path UTF8String];

So you may not change the pointed data using the pointer pos

*pos = 0;

that shall be also declared with the qualifier const because the function strchr returns a constant pointer.

const char* pos = strrchr (szPathName, '/');

Make the pointer szPathName to point to non-constant data.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Sorry I am showing my newbieness with c++ here, how would I make that point to non-constant data? – user1695971 May 08 '20 at 11:16
  • 1
    @user1695971 You need to declare the pointer szPathName without the qualifier const and the pointer shall point to a non-constant character array. You may not for example change a string literal. – Vlad from Moscow May 08 '20 at 11:18
  • hmm I did attempt that already but was faced with a new error `Cannot initialize a variable of type 'char *' with an rvalue of type 'const char * _Nullable'` when removing the const qualifier... – user1695971 May 08 '20 at 11:20
1

It doesn't appear that you've done anything since your previous question, SO does really require you show some effort.

Let's step through your original code to hopefully help understanding of the issue:

I am thinking this is a later Xcode issue (I am using Xcode 11) as this code was fine previously in older versions.

It's not an Xcode issue per se, your code was always wrong but fortunately for you producing the desired result, it is just that error and warning messages have improved.

const char* szPathName = [path UTF8String];

This line takes an NSString value referenced by path, calls the method UTF8String on it which returns a pointer to a C string value, and stores that reference in szPathName. From Objective-C you will know that an NSString value is immutable, you cannot change the characters in the string. The UTF8String method returns a pointer to a constant C string value and so szPathName has the type const char * – NSString and const char * are the types in Objective-C and C respectively for variables which store references to constant strings; similarly NSMutableString and char * are the types for references to mutable strings.

char* pos = strrchr (szPathName, '/');

This line of code searches for the rightmost / in the C string and returns a pointer to it. As you found from your last question strrchr() in C++ returns a const char * if passed a const char *. This line of code was always wrong but it seems an earlier compiler did not report the error, which is to type pos as a pointer to a mutable string which it is not. Just as assigning an NSString * value to an NSMutableString * typed variable in Objective-C does not make the referenced string mutable, assigning a const char * value to an char * typed variable in C does not make the reference C string mutable.

*pos = 0;

This line is correct, as the type of pos is char *, but also incorrect as the value stored in pos happens to be a pointer to an immutable C string.

Your code has previously worked as C is lax when it comes to mutability/immutabilty, and fortunately writing into a C string stored inside an instance of NSString (see UTF8String documentation) didn't cause any problems.

You are not going to solve your problem but adding or removing const in various places, doing so may result in code which appears to work but it could easily break at any time.

As suggested to you in your last question rather than try to fix the C code a line at a time, especially given your declared lack of knowledge of C(++), you would be better off looking at what this code is trying to do and to code that as much as possible in Objective-C.

So what is the aim of the code?

  1. Start with a path to a file stored in path, as an NSString value
  2. Determine the parent folder/directory of that file
  3. Pass that parent folder as a constant C string value to the function CreateFaceFatted

You already have the code to obtain the file path and store it in path, so step 1 requires no work.

You also know how to produce a pointer to a constant C string from an NSString value – use UTF8String. So step 3 is covered.

That leaves step 2. Your current code tries to do it after the conversion to a C string, and that you don't know how to do. But you do know Objective-C, is there a method/property on NSString which takes a file path and returns the path of the containing folder/directory? A good place to look would be the documentation.

Hopefully that will help you understand your issue and hence get you quickly to the solution.

CRD
  • 52,522
  • 5
  • 70
  • 86