I have a multi-platform project, running on Windows, Linux and iOS right now, but I have stumbled upon a undesirable problem with Objective-C.
I have, unfortunately, chose the name exp for one of my types (expressions, pretty reasonable given the number of occurrences in my code), but Objective-C somehow includes the math.h header by default, creating a name-clash.
I tried to comment out everything in the .pch (the prefix file included by default before every source file), and exp is still flagged as redefinition.
Does anybody know how to not include math.h in a source file inside Objective-C project?
Objective-C does not have a formal specification, but it inherits features from C. In C, programs should not use identifiers from the standard headers, even if they do not include those headers. So, you should not use “exp” for your own identifiers.
If you insist upon using “exp”, you might be able to work around the issue with a preprocessor statement:
#define exp MyExp
This will allow you to write “exp” in your source code as if it were one of your identifiers. Since the preprocessor will change it to “MyExp”, the compiler will see “MyExp” as the identifier and will not complain.
This will cause a number of problems, such as the identifier showing up as “MyExp” in object code information and in debugging tools and causing inability to use exp from math.h in the future.
Related
I am learning Objective-C, but can't understand one thing with the frameworks. Each framework in objective-C contains header files which contain only #interface part. That means that header files only declare difference methods and do not implement them. Is this implementation part hidden in the frameworks or something, because I can't get how it works.
Thank you in advance for your answers!
Is this implementation part hidden in the frameworks or something
Well, sort of. It's compiled (the actual source code is not present neither in the SDK nor in the OS) and only the binary executable code is contained within the dynamic library that resides inside the framework.
It is still possible to use them (i. e. link against them), obviously (see this for an explanation), but you cannot edit the source code. In theory, you could try binpatching them (i. e. disassembling, analyzing and editing the executable file using a hex editor or something), but that's neither recommended (you can screw up your entire system if you do one slight thing wrong), nor easy.
I know there are a lot of questions on this topic, and I've looked through a fair number of them. However I am still having problems.
I started writing a test program for a prototype PCB, and now that it's grown to nearly 1000 lines I'm trying to break it up into libraries that I can use for particular functions.
I thought this would be very simple. Make .c and .h files for each library that I need. I.e. I would have OLED.h and OLED.c for functions that control an OLED display. Copy the appropriate functions/definitions into each file. Then copy these files into the solution in Atmel Studio. I put them into the src folder under the project name.
However, this doesn't work! I get an exceedingly long list of errors. All of the things that are defined in the .h file are apparently undefined as far as the compiler is concerned. I also get many error messages of the type "unknown type name int16_t/uint16_t/uint8_t/etc..." That part is really baffling to me. Why should it matter that functions are in an external library, now the compiler doesn't understand what those data types mean?
So, this is probably a stupid problem to have. I don't want Atmel Studio to control my libraries by wrapping them up in some "library project" or somethig, I want to put them in a folder of my choosing and add them when I need them. I've searched for answers to this problem and I find long tutorials about changing the compiler settings for the project, the linker settings, etc... I tried this tutorial and still no dice: http://www.engblaze.com/tutorial-using-avr-studio-5-with-arduino-projects/#setup
I also can't find a way to add something by right clicking the project and clicking "Add." It wants me to find .a files. The "Add Library" dialog box in Atmel Studio is awful, it seems.
Surely it can't be that convoluted to just add a library to an existing project and have it function normally?! I've used PICs in the past and coming to Atmel I've found horrible documentation and a weird super-slick super-fly whizz bang interface that can't leave well enough alone and obfuscates simple function. What can I do to add these libraries?
UPDATE: Seemed to answer my own question. Turns out I needed to include all of the libraries to recognize data types and whatnot into the .c file. I somehow assumed this only had to be done in the main file but obviously I was mistaken. Adding asf.h seems to work well as it includes all of the MCU specific port definitions/names and all of that. All good for now!
Adding library files to a solution should be simple. Go to the Solution Explorer, right-click on your solution, and go to "Add->Existing Item". If you want to add a pre-existing library and keep it in a separate folder from your solution, click the arrow next to "Add" and choose "Add as link". That saves many headaches due to having a duplicate copy of your library in your solution folder, and files not staying up-to-date.
You are right in saying that you need to include the necessary header files in the .c files where they are used.
The compiler compiles each C file separately, and then links them together at the end, so you got the error unknown typename int_* because the compiler had not seen the relevant header in the context of compiling that C file.
You also seem to be in some confusion as to the difference between definition and declaration.
A function is:
Declared in the header file. This means there is a function prototype, e.g. int some_func(char some_var); which tells the compiler that the function exists, but does not tell it what it is. This is necessary because the compiler only looks at one C file at a time, so needs to be told that other functions exist.
Defined in the C file.This is the actual function body, i.e. int some_func(char some_var) { do_stuff(some_var); }. After compilation of each individual C file in isolation, the linker is called to put all the pieces together and give you your final binary, which you flash to the device.
A function can be (and must be) defined only once, but may be declared many times - even in the same file, so long as the declarations are not conflicting.
OK, I know there have been other posts about how you can't actually strip Objective-C symbols from an OS X binary because they're necessary for Obj-C to work at all, but my case is a bit different.
I have a single binary which is a bundle. It is intended to be used as either a VST plugin, or an AudioUnit plugin. The idea is that the binary contains all the entry points for both formats, and you just compile it once, and then name one copy with ".vst" for the VST version, and ".component" for the AU version. (This is using the JUCE framework BTW.)
The problem is that for the AU side, you must export an Obj-C class for creating the Cocoa UI view. On the VST side, this class will never be used. But if you have a host like Ableton Live which allows you to simultaneously load both AU and VST versions of the same plugin, now we run into the typical Obj-C namespace collision issue.
On the VST side, that particular Obj-C class will never get used. So what I'd like to do is to strip those Obj-C classes from the resulting binary using "strip". This still maintains the advantage of just compiling everything once for both formats.
Anyway, I've tried using "strip -R stripfile.txt <path to binary>", where stripfile.txt contains the symbols I want to strip, but it always fails saying that the symbols can't be found in the binary. I've tried mangling the names in the strip file, but that doesn't help (or I'm doing it wrong).
Here are the relevant symbols that I want to strip, as output by "nm -m":
000000000003bb00 (__TEXT,__text) non-external -[JuceDemoProjectAU description]
000000000003bb60 (__TEXT,__text) non-external -[JuceDemoProjectAU interfaceVersion]
000000000003ba00 (__TEXT,__text) non-external -[JuceDemoProjectAU uiViewForAudioUnit:withSize:]
0000000000b02398 (__DATA,__objc_data) external _OBJC_CLASS_$_JuceDemoProjectAU
0000000000b023c0 (__DATA,__objc_data) external _OBJC_METACLASS_$_JuceDemoProjectAU
Any ideas?
BTW, I have subsequently been able to dynamically register the class in question (using a unique name), which also solves the problem. However, if I could get strip working, I could potentially deploy a solution for already existing binaries in the field.
You can not just simply strip a class from a binary. What you can do however is to trick the Objective-C runtime into believing your plugin does not contain any Objective-C code. Just change __objc_imageinfo into __objc_imageinfX for example in your VST plugin binary. You can do it easily with perl:
perl -pi -e 's/__objc_imageinfo/__objc_imageinfX/g' <path to binary>
After patching the VST plugin, all the Objective-C initialization will be bypassed and you won’t see this error message: Class JuceDemoProjectAU is implemented in both …/VSTPlugin and …/AUPlugin. One of the two will be used. Which one is undefined.
Beware, you should really not use this trick! The appropriate solution to your problem is either to compile two different version of your plugin or to register classes dynamically as others suggested.
There was a thread about something similar to this on the coreaudio-list last year: Collision between Cocoa classes for AU and VST plugins.
The solution offered was to register the classes dynamically which is what you say you already have working. If there was a way to strip the symbols like you wanted, I'm sure these guys would have known about it.
I just seem to hit one error after another when dealing with larger projects in Xcode. This time, GCC is complaining of a duplicate definition for a struct-printing function - one where it is actually defined (in a different file), and one where it is used (in the driver).
The specific error I'm getting is this:
ld: duplicate symbol _fprintConfiguration in
/.../bits.build/Objects-normal/x86_64/Block.o and
/.../bits.build/Objects-normal/x86_64/bits.o
where Block.o contains the definition and bits.o contains the driver.
I've done some research on this already, but it seems that every problem exists with people actually defining it twice by virtue of #include, but in all my files I only use #import. Isn't the #import directive supposed to 'intelligently' include files? Are there any other reasons I could be getting this error? Are there any other solutions I can try?
Thanks for your help :)
The problem is that you're including the same definition in multiple translation units (both Block.o and bits.o). To fix this, declare the function inline or move the definition to a (single) source (non-header) file.
This is orthogonal to the question of #include vs. #import. That's about including the same code multiple times in the same translation unit.
To support multiple platforms in C/C++, one would use the preprocessor to enable conditional compiles. E.g.,
#ifdef _WIN32
#include <windows.h>
#endif
How can you do this in Ada? Does Ada have a preprocessor?
The answer to your question is no, Ada does not have a pre-processor that is built into the language. That means each compiler may or may not have one and there is not "uniform" syntax for pre-processing and things like conditional compilation. This was intentional: it's considered "harmful" to the Ada ethos.
There are almost always ways around a lack of a preprocessor but often times the solution can be a little cumbersome. For example, you can declare the platform specific functions as 'separate' and then use build-tools to compile the correct one (either a project system, using pragma body replacement, or a very simple directory system... put all the windows files in /windows/ and all the linux files in /linux/ and include the appropriate directory for the platform).
All that being said, GNAT realized that sometimes you need a preprocessor and has created gnatprep. It should work regardless of the compiler (but you will need to insert it into your build process). Similarly, for simple things (like conditional compilation) you can probably just use the c pre-processor or even roll your own very simple one.
AdaCore provides the gnatprep preprocessor, which is specialized for Ada. They state that gnatprep "does not depend on any special GNAT features", so it sounds as though it should work with non-GNAT Ada compilers. Their User Guide also provides some conditional compilation advice.
I have been on a project where m4 was used as well, with the Ada spec and body files suffixed as ".m4s" and ".m4b", respectively.
My preference is really to avoid preprocessing altogether, and just use specialized bodies, setting up CM and the build process to manage them.
No but the CPP preprocessor or m4 can be called on any file on the command line or using a building tool like make or ant. I suggest calling your .ada file something else. I have done this for some time on java files. I call the java file .m4 and use a make rule to create the .java and then build it in the normal way.
I hope that helps.
Yes, it has.
If you are using GNAT compiler, you can use gnatprep for doing the preprocessing, or if you use GNAT Programming Studio you can configure your project file to define some conditional compilation switches like
#if SOMESWITCH then
-- Your code here is executed only if the switch SOMESWITCH is active in your build configuration
#end if;
In this case you can use gnatmake or gprbuild so you don't have to run gnatprep by hand.
That's very useful, for example, when you need to compile the same code for several different OS's using even different cross-compilers.
Some old Ada1983-era compilers have a package called a.app that utilized a #-prefixed subset of Ada (interpreted at build-time) as a preprocessing language for generating Ada (to be then translated to machine code at compile-time). Rational's Verdix Ada Development System (VADS) appears to be the progenitor of a.app among several Ada compilers. Sun Microsystems, for example, derived the Ada SPARCompiler from VADS and thus also had a.app. This is not unlike the use of PL/I as the preprocessor of PL/I, which IBM did.
Chapter 2 is some documentation of what a.app looks like: http://dlc.sun.com/pdf/802-3641/802-3641.pdf
No, it does not.
If you really want one, there are ways to get one (Use C's, use a stand-alone one, etc.) However I'd argue against it. It was a purposeful design decision to not have one. The whole idea of a preprocessor is very un-Ada.
Most of what C's preprocessor is used for can be accomplished in Ada in other more reliable ways. The only major exception is in making minor changes to a source file for cross-platform support. Given how much this gets abused in a typical cross-platform C program, I'm still happy there's no support for it in Ada. Very few C/C++ developers can control themselves enough to keep the changes "minor". The result may work, but is often nearly impossible for a human to read.
The typical Ada way to accomplish this would be to put the different code in different files and use your build system to somehow choose between them at compile time. Make is plenty powerful enough to help you do this.