Error and warnings in Xcode when declaring Array of NSString* as a global extern - objective-c

I am declaring an array of NSString* in a header file of a class.
PolygonShape.h
NSString* POLYGON_NAMES[] = {#"Invalid Polygon", #"Monogon", ...};
Now I am using this in PolyginShape.m as follows:
- (NSString*) name {
return (POLYGON_NAMES [self.numberOfSides]);
}
numberOfSides is an iVar which will indicate the index at which the polygon name is stored
So far so good ... it was compiling without any errors
Then I added PolygonShape.h in my file that implements main method (note: these does not have any class definition and call functions C-Style rather than obj-c Style)
#import "PolygonShape.h"
Now when I compile, I am getting a build (linking) error
ld: duplicate symbol _POLYGON_NAMES in /Users/../Projects/CS193P/1B/What_A_Tool/build/What_A_Tool.build/Debug/What_A_Tool.build/Objects-normal/i386/PolygonShape.o and /Users/../Projects/CS193P/1B/What_A_Tool/build/What_A_Tool.build/Debug/What_A_Tool.build/Objects-normal/i386/What_A_Tool.o
collect2: ld returned 1 exit status
So I went thru stack overflow and other forums and mostly the advice was to make the global variable extern and so I did ...
extern NSString* POLYGON_NAMES[] = {#"Invalid Polygon", #"Monogon" .. };
However I am still getting the linking error and also getting 2 warnings now that says
warning: 'POLYGON_NAMES' initialized and declared 'extern'
at both the places where i am importing PolygonShape.h
What am I missing here?
Thanks.

In your header file declare the array as:
extern const NSString* POLYGON_NAMES[];
In your source file, define the array and initialize the contents:
const NSString* POLYGON_NAMES[] = {#"Invalid Polygon", #"Monogon" };

Related

How can Poplar codelets include code from other header files?

Is it possible for codelets to reference code in other files, like header files?
If I have a codelet file
//FileA.cpp
#include "FileB.h"
class SomeCustomVertex : public Vertex {
public:
bool compute() {
int a = SomeConstantDefinedInFileB;
}
...
}
and some other "codelet" file
//FileB.h
const int SomeConstantDefineInFileB = 42;
and in the host graph program:
graph.addCodelets({"codelets/FileA.cpp", "codelets/FileB.h"});
I get a compile error from popc:
fatal error: 'FileB.h' file not found
#include "FileB.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
terminate called after throwing an instance of 'poplar::graph_program_compilation_error'
what(): Codelet compilation failed (see compiler output for details)
I figured this out.
Graph::addCodelets has a parameter StringRef compileFlags = "", which you can use to inject compiler options.
popc --help shows an option
-I arg Add directory to include search path
So when I use graph.addCodelets({"codelets/FileA.cpp"}, "-I codelets"); in the host program, and have my codelets in 'codelets' subdirectory, this works. No need to explicitly list the ".h" files in the arguments.
Incidentally, also a good way to ensure compiler optimisation (-O3) for the custom codelets.

How to use `git_note` from libgit2?

I've got code (where commit_id is already set) like:
git_note* note;
git_note_read(&note, repo, "refs/notes/label", &commit_oid);
printf("%s\n", note->message);
git_note_free(note);
It doesn't compile, complaining:
.../importer_test.cc:103:22: error: member access into incomplete type 'git_note'
printf("%s\n", note->message);
^
.../include/git2/types.h:160:16: note: forward declaration of 'git_note'
typedef struct git_note git_note;
If I just copy/paste from src/notes.h into this file:
struct git_note {
git_oid id;
git_signature *author;
git_signature *committer;
char *message;
};
It compiles and runs correctly. But surely that's not the right solution?
git_note is an opaque type. You're not meant to access members of the data directly. You should be using the accessor functions to read from it. In your case, you would want to use git_note_message() to get the message.

Importing a configuration file gives mach-o-linker

Its very strange, i have a .h file with many const and variables .
I have tWo classes that use him, hence import him:
classA , and classB with : ( #import "configurations.h" )
Now another new class that i have added, C , came in , and when i am trying to do the same with him, import the configuration file - i get a mach-o-linker error .
Check this out : even if the new class C is empty(!) i cant add that configuration file and get the same error . i have tried also with new classes , and its the same .
I could only add it then , to A B and now, no more importing !
EDIT
Ok, i now get it , first its not happen in class A and B because: A.m and B.mm hence i can import them both with that .h file .
Than the problem is probably because i dont use extern with my consts in the .h file ?
(i have tried extern and still got errors) , i create somehow 2 copies of consts from .h :
How i define them in .h file ? just like that :
const int wordSize=8;
const int numOfWords=8;
Whay am i missing here ?
(there is some other class D ,that import A B C if its matter )
.h file is for declarations
.m file is for definitions
It means no "=" signs in .h, no method implementations. If you have constant:
configurations.h
extern const int wordSize;
extern NSString * const someStringConst;
configurations.m
const int wordSize = 8;
NSString * const someStringConst = #"someStringConst";
If you import your
configurations.h
const int wordSize = 8;
from multiple files, compiler generates _wordSize symbol for every file that imported configurations.h
Linker for sure cannot resolve these duplicated symbols - so the best approach is to get rid of definitions in your .h file using extern declaration like i've shown above.

Firebreath MethodConverter.h invalid initialization

Hi I created a firebreath project. I added this methods to the default generated code:
In the application API header file (MYAppAPI.h):
FB_JSAPI_EVENT(bgp, 3, (const FB::variant&, bool, int));
std::string bgp(std::string& val);
In the application API source file (MAppAPI.mm I am using objective-c):
registerMethod("bgp", make_method(this, &MyAppAPI::bgp));
std::string MyAppAPI::bgp(std::string& val){...}
But when I build the code, I am getting this error:
...firebreath/src/ScriptingCore/MethodConverter.h:115: error: invalid initialization of non-const reference of type 'std::string&' from a temporary of type 'std::basic_string, std::allocator >'
Any ideas?
that should read:
std::string MyAppAPI::bgp(const std::string& val){...}
note the const. You can't pass things by reference into a JS function, so it won't let you pass a non-const reference.

Separating Code To Be Organized

I'm building a zipper application, but it has a declaration that I want to separate it in another file (compress-file.m), but only when I separate the files I got an error when compiling with a variable, see it:
[ubuntu#eeepc:~/Desktop] make
This is gnustep-make 2.0.2. Type 'make print-gnustep-make-help' for help.
Making all for app LeafZip...
Creating LeafZip.app/....
Compiling file main.m ...
main.m: In function ‘main’:
main.m:7: error: ‘PATH_MAX’ undeclared (first use in this function)
main.m:7: error: (Each undeclared identifier is reported only once
main.m:7: error: for each function it appears in.)
main.m:12: warning: implicit declaration of function ‘compressFile’
main.m:7: warning: unused variable ‘outFileName’
make[1]: *** [obj/main.o] Error 1
make: *** [LeafZip.all.app.variables] Error 2
Also see the line 7 of main.m file:
char outFileName[PATH_MAX] = { 0 };
And see some lines of compress-file.m:
#include <stdio.h>
#include <zlib.h>
#include <limits.h>
/* Buffer to hold data read */
char buf[BUFSIZ] = { 0 };
size_t bytes_read = 0;
gzFile *out = gzopen(outFileName, "wb");
I know that is Objective-C extension, but it's only because when I solve this problem I will need to continue the development in Objective-C. What I need to do to correct this?
PATH_MAX is not always defined by including <limits.h>. If you want to use it, you probably need to fall back on the fragment:
#include <limits.h>
#ifndef PATH_MAX
#define PATH_MAX _POSIX_PATH_MAX /* Or possibly _XOPEN_PATH_MAX */
#endif /* PATH_MAX */
Did you even include limits.h in your main program? If not, you need to do so.
Looks like main.m needs to #include <limits.h>. It also seems like it will need to include a header describing compressFile (which I guess you moved into compress-file.m.