Archive | GCC RSS for this section

Fun With Makefiles

Lately, I’ve been toying with the idea of trying my hand at some graphics programming. After spending the better part of yesterday trying to figure out how to even get started, I think I have a way ahead.

Building hello triangle using OpenGL is a fairly involved task. First, you need to settle on a graphics library. There are two choices here: OpenGL and DirectX. Obviously, I’ll be selecting OpenGL in order to avoid Microsoft vendor lock-in.

Next, you need a library to display a window for you. Sure, you could do it yourself, but then you’d get bogged down in a quagmire of platform specific issues. If you’ve been reading the blog, you know I don’t care for this sort of platform dependent nonsense, so I’ve tenatively settled on SDL 2. SDL is a cross platform multimedia library that handles sound, input, window creation, and the like. I plan to use this, in conjunction with an OpenGL context to do my work.

After you have that in order, you need an OpenGL Function Loader. Apparently the folks at Khronos were inspired by DMP Photobooth’s module system, there isn’t some opengl.h file you can just include and get your functions: you get to call dlopen and use dlsym to get function pointers. This wouldn’t be a huge issue if there were just a few functions, but there are thousands of them. In light of this, I’ve elected to go with GL3W for the time being. GL3W is a simple python script that generates a .c file containig the function pointers, and a .h to include.

All of this leads us to the topic of today’s post. How do we build this mess of libraries and random .c files?

We’ll Make it Work

The obvious answer here is that we need to use some sort of build system. Given my past experience with the abominations produced by NetBeans, I’ve elected to roll my own. Let’s take a look:

.DEFAULT_GOAL := all

First, we have the default goal. By default, the default goal is the first one in the file. However, I like to make things explicit. Here, we set the default goal to “all”, which builds the code for all targets.

Next, we define some variables:

CC = gcc COMPILE_FLAGS = -c -g -Wall -Wextra -std=c11 $(OPTIMIZE_LEVEL) LINK_FLAGS = -g -Wall -Wextra -std=c11 $(OPTIMIZE_LEVEL) OPTIMIZE_LEVEL = -Og LINKER_LIBS = -lSDL2 -ldl -lGL RM = rm -f UNIVERSAL = gl3w gl_includes.h

The first variable, CC is built-in, and defaults to gcc. Again, I’m redefining it here to be explicit. After that, I define COMPILE_FLAGS and LINK_FLAGS, which are the flags I want to pass when I’m compiling someing to be link at a future time, and when I’m compiling and linking respectively. I define OPTIMIZE_LEVEL separately, because I want to potentially change it, and I don’t want to have to worry about if the two are in sync.

LINKER_LIBS are the libraries I’m going to be using. RM is the rm command, with flags, to be used in the clean target. UNIVERSAL is a list of files and targets that all buid targets depend on.

all : chapter1 chapter2 chapter3 chapter4 chapter5 chapter6 chapter7 chapter8 \ chapter9 chapter10 chapter11 chapter12 chapter13 chapter14 chapter15 \ chapter16 chapter17 chapter1 : $(UNIVERSAL) chapter1.c @echo "Building chapter 1:" $(CC) -o chapter1 $(LINK_FLAGS) chapter1.c gl3w.o $(LINKER_LIBS) ... chapter17 : $(UNIVERSAL) @echo "Building chapter 17:"

Here we have the meat of our makefile. The tutorial I’m following has 17 chapters, and I’ll be building code from each. We have an “all” target that builds each chapter, and we have a target for each chapter that builds an executable. Each chapter target depends on UNIVERSAL and its own files.

gl3w : gl3w.c GL/gl3w.h GL/glcorearb.h $(CC) $(COMPILE_FLAGS) gl3w.c

Here we build the source files that GL3W produces. I’m compiling it into a .o file so that it can be linked into the code for the various chapters.

clean: @echo "Deleting .o files..." $(RM) *.o @echo "Deleting core..." $(RM) core @echo "Deleting chapters..." $(RM) chapter1 $(RM) chapter2 $(RM) chapter3 $(RM) chapter4 $(RM) chapter5 $(RM) chapter6 $(RM) chapter7 $(RM) chapter8 $(RM) chapter9 $(RM) chapter10 $(RM) chapter11 $(RM) chapter12 $(RM) chapter13 $(RM) chapter14 $(RM) chapter15 $(RM) chapter16 $(RM) chapter17

Finally, I have my clean target. Here we delete all the cruft that builds up in the build process.

It’s a simple makefile, but I feel it’ll make this process easier. I can just do the exercises and hopefully spend less time fiddling with gcc.

Again, This Time In Reverse!

Today we’ll be doing Exercise 5 from The C Programming Language. Today’s exercises aren’t terribly challenging, but there is some good stuff in here. The problem is:

Modify the temperature conversion program to print the table in reverse order, that is, from 300 degrees to 0.

I bet you thought we were done with temperature conversion, didn’t you? I’m right there with you, but luckily for us, this is also the section that introduces the for loop, so this is much less tedious. The new program for modification:

#include <stdio.h> int main (int argc, char ** argv) { for (int fahr = 0; fahr <= 300; fahr = fahr + 20) { printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32)); } }

I made a few minor modifications. I gave main the correct signature to keep gcc from complaining, and I also moved the initialization of fahr to the loop. As you may know this is not valid C, and the compiler will throw an error. You might also know that this was made to be valid C in the C 99 revision. To compile this, you just need to add the -std=c99 flag to your gcc call.

To complete this exercise, you only need to modify the loop declaration. Change this line…

for (int fahr = 0; fahr <= 300; fahr = fahr + 20)

…to this…

for (int fahr = 300; fahr >= 0; fahr = fahr - 20)

Pretty straight forward stuff here. fahr starts at 300 instead of 0, and the loop continues so long as it remains greater than 0. Instead of adding 20 each iteration, we subtract it. This can be compiled like so:

gcc -std=c99 -Wall ex5.c -o ex5

In Haskell

Unfortunately, the authors of The C Programming Language did not see fit to include a starting Haskell program for us to modify. This seems like a pretty serious oversight to me, but we’ll just have to make due. Luckily for us, we can use the temperature conversion program I wrote for the last entry in this series. This program handles conversions, and we can use it to produce a table of all conversions between 0 and 300 degrees.

While I’ve established that Haskell does in fact have loops, we won’t be using them here. Instead we’ll be using ranges, functors, and sequencing to solve this problem in a more functional way.

First, we need a list of every 20th number between 0 and 300:

[300.0, 280.0 .. 0.0]

The .. there basically says “You get the idea, do that.” If you put enough information into it so that the compiler can figure out the pattern, and start and end points, the compiler will fill the rest in. In this case, I gave the first two values, telling the compiler I want increments of 20, and I gave it the last value so it knows where to stop.

Unfortunately, as you recall, my conversion program needs members of the Temperature typeclass. Surely I don’t plan to make Double a member, right? Right. We need to map a function over this list to produce a list of Temperatures. But what function should we use?

Something that beginning Haskellers may not realize is that constructors are in fact functions!

Prelude> :t Just Just :: a -> Maybe a Prelude> :t Left Left :: a -> Either a b

…and of course…

*Main> :t Fahrenheit Fahrenheit :: Double -> Fahrenheit

That’s right, we can map Fahrenheit over a functor just like any other function!

map Fahrenheit [300.0, 280.0 .. 0.0]

This will produce a list of every 20th Fahrenheit temperature between 300 and 0. However, we aren’t done yet. We actually need a list of Conversions, because this type is required for our insertConv function. To get this we can map toConversion over this list:

map toConversion $ map Fahrenheit [300.0, 280.0 .. 0.0]

…but that’s starting to get a bit ugly, there must be a better way. Normally, I’m not terribly fond of function composition, in this case it will make our life easier.

Function Composition

Haskell provides an operator . that is used for function composition. Let’s take a look at its type:

Prelude> :t (.) (.) :: (b -> c) -> (a -> b) -> a -> c

The composition operator takes a function that takes some type b as an argument, and that returns some type c. It takes a second function that takes some type a as an argument, and that returns some type b. Finally, it returns some type c.

What does this do for us? Basically, it takes a function a -> b, and a function b -> c, and turns them into a function a -> c. Let’s see an example:

Prelude> :t show show :: Show a => a -> String

The function show takes a member of the Show typeclass and returns a String.

Prelude> :t putStr putStr :: String -> IO ()

The function putStr takes a String, and returns an IO action.

Prelude> :t putStr . show putStr . show :: Show a => a -> IO ()

When we compose the two functions, we get a function that takes a member of the Show typeclass, and returns an IO action.

Logically, calling putStr . show someShowable is the same as calling putStr $ show someShowable or putStr (show someShowable). However, putStr . show is a valid function, where putStr $ show and putStr (show) are compiler errors if you don’t give show an argument.

How does this help us?

*Main> :t Fahrenheit Fahrenheit :: Double -> Fahrenheit *Main> :t toConversion toConversion :: (Temperature a, Temperature b) => a -> (a, b) *Main> :t toConversion . Fahrenheit toConversion . Fahrenheit :: Temperature b => Double -> (Fahrenheit, b)

By composing toConversion and Fahrenheit, we end up with a function that takes a Double as an argument and returns a Conversion from Fahrenheit. We can then map this function over our list of Doubles:

map (toConversion . Fahrenheit) [300.0, 280.0 .. 0.0]

Next, we need to turn these Conversions into TableBuilders. This is a simple matter of composing insertConv:

map (insertConv . toConversion . Fahrenheit) [300.0, 280.0 .. 0.0]

The type of this new function is:

:t (insertConv . toConversion . Fahrenheit) (insertConv . toConversion . Fahrenheit) :: Double -> TableBuilder ()

…or at least it would be if the type inferrer could figure out the type of toConversion. Unfortunately for us, it can’t because the implementation is purposely ambiguous. We need to add a type signature to it:

(insertConv . (toConversion :: Fahrenheit -> (Fahrenheit, Celsius)) . Fahrenheit)

Sequencing

Now we are ready to create our table. This part is actually very easy. Thanks to the library function sequence_ we won’t even need a do block. What does this function do? Let’s look at its signature:

Prelude> :t sequence_ sequence_ :: Monad m => [m a] -> m () Prelude> :t sequence sequence :: Monad m => [m a] -> m [a]

There are two variations of this function. The first, sequence_ evaluates each monadic action, and ignores the results. Basically, suppose we have some function: func :: a -> Monad b

let mList = map func ["foo", "bar", "baz"] in sequence_ mList

…is equivalent to…

do func "foo" func "bar" func "baz" return ()

The second variation evaluates each monadic action, and returns a list of all the results. Suppose we have our same function: func :: a -> Monad b

let mList = map func ["foo", "bar", "baz"] in sequence mList

…is equivalent to…

do foo <- func "foo" bar <- func "bar" baz <- func "baz" return [foo, bar, baz]

If you have a list of monads, you can use sequence or sequence_ to have them all evaluated. Use sequence if you care about the resulting values, use sequence_ if you only care about the monad’s side effect. Which do we want? Let’s look at the signature of insertConv:

*Main> :t insertConv insertConv :: (Temperature a, Temperature b) => Conversion a b -> TableBuilder ()

If we were to use sequence, we’d get a resulting value with the type TableBuilder [()]. Since nobody has any use for a list of empty tuples, we’ll be using sequence_.

So, what does our main look like?

main = do temps <- return (map (insertConv . (toConversion :: Fahrenheit -> (Fahrenheit, Celsius)) . Fahrenheit) [300.0, 280.0 .. 0.0]) putStrLn $ prettyPrint $ buildTable $ do sequence_ temps

This produces the following output:

------------------------------ || Fahrenheit || Celsius || ------------------------------ || 300.0 |> 148.9 || || 280.0 |> 137.8 || || 260.0 |> 126.7 || || 240.0 |> 115.6 || || 220.0 |> 104.4 || || 200.0 |> 93.3 || || 180.0 |> 82.2 || || 160.0 |> 71.1 || || 140.0 |> 60.0 || || 120.0 |> 48.9 || || 100.0 |> 37.8 || || 80.0 |> 26.7 || || 60.0 |> 15.6 || || 40.0 |> 4.4 || || 20.0 |> -6.7 || || 0.0 |> -17.8 || ------------------------------

K&R Challenge 2: The Specter of Undefined Behavior

Continuing with the K&R Challenge, today we’ll be doing exercise 2:

Experiment to find out what happens when printf‘s argument string contains \c, where c is some character not listed above.

Basically, we’ll be trying to print “\c” to the screen, and seeing what C does.

In C

The code for this is very simple:

int main (int argc, char ** argv) { printf("Trying to print: \c\n"); return 0; }

Like last time, we’ll compile it using:

gcc -Wall ex2.c -o ex2

Right away, you should get a compiler warning:

ex2.c: In function ‘main’: ex2.c:10:11: warning: unknown escape sequence: '\c' [enabled by default] printf("Trying to print: \c\n");

Notice that it is a warning, not an error, and that the compilation still succeeded and produced an executable. My friends, you have just witnessed Undefined Behavior. Undefined behavior is one of the defining aspects of C. Technically, it’s a feature, not a bug, and it is both a blessing and a curse.

It’s a blessing in that it’s one of the things that enables C’s unmatched performance. It’s a curse in that the compiler is allowed by the spec to do whatever it wants when it encounters undefined behavior: it could do something really helpful, it could segfault, or it could delete your hard drive. It could even unleash lions in your house and there’s nothing the police or congress could do about it.

Moral of the story: don’t use undefined behavior unless you really know what you’re doing. Even then, I’d argue it’s a code smell.

So, what happens when you run the compiled executable? Always fearless in the pursuit of truth, I ran it. The following was printed to the console:

Trying to print: c

The GNU C Compiler decided to be nice and just strip the “\”, then print the message. It’s a good thing I have managed to avoid angering Richard Stallman, because gcc could very well have kidnapped my wife. That would have been a problem.

And In Haskell

Nothing about this exercise relies on the behavior of printf, therefore even though Haskell has it, I’ve elected not to use it. The implementation of this exercise in Haskell looks like this:

main :: IO () main = putStrLn "Trying to print: \c\n"

As before, this can be run using:

runhaskell ex2.hs

…but when you try it, the following error is displayed, and compilation fails:

ex2.hs:2:62: lexical error in string/character literal at character 'c'

Where C allowed the undefined escape sequence as undefined behavior, Haskell throws a compilation error. This is a Good Thing. Undefined behavior is a prolific source of bugs, and while I understand why it’s allowed, I can’t say that I agree that the tradeoff is worth it. Luckily for us, this isn’t a feature unique to Haskell. Most high level languages don’t have undefined behavior. Unfortunately, this is one of the reasons that most programming languages are orders of magnitude slower than C.

Regardless, undefined behavior is a fact of life for the C programmer. It’s one of the tradeoffs they make to use the language. These design decisions were made decades ago, and are unlikely to change. For this reason, this is a good exercise.

The families of those who were turned to stone by their compilers after doing this exercise are in our prayers…

Introducing The K&R Challenge

Recently, I inherited a copy of The C Programming Language, aka “K&R”. I was borrowing it, and today I tried to give it back, but the book’s former owner didn’t want it back. I was going to put it back in it’s deep dark box, likely to never been seen again, when I had a thought. Surely there’s something in this ancient tome of knowledge waiting for me.

On a whim, I decided to go through the exercises. This post marks the first task in the K&R Challenge.

The rules: the book is about the C programming langauge. The book is not about glib, linux programming, gtk, or any other library or framework. Therefore, the solutions to the exercises should only use the standard library, unless the book specifically calls out a library. I will attempt to stay as true to the wording of the excercise as possible.

Seems pretty straightforward, right? Well this brings us to part two; after doing an excercise in C, I will do it in Haskell. For these examples, I will attempt to implement the program in idiomatic Haskell. The ends are more important than the means here, so if the example calls out a specific function or technique, I will only use it if I feel it’s the best way to do it. For the Haskell portion, I will minimize the use of libraries as well.

So, without further ado…

Excercise 1.1

Excercise 1.1 is simply to implement “Hello World” Shockingly this is a trivial problem in C:

#include "stdio.h" int main (int argc, char ** argv) { printf("Hello World!\n"); return 0; }

First, we include stdio.h to gain access to printf, then we say hello to the world. You’ll notice I put curly braces on their own lines. Sue me.

To compile this, assuming you’re using gcc, enter the following:

gcc -Wall ex1.c -o ex1

Running the produced program produces the output:

Hello World!

Amazing!

In Haskell, this is even easier:

main :: IO () main = putStrLn "Hello World!"

As putStrLn and the IO monad are in prelude, this program does not require any imports.

To run this, simply type the following at the prompt:

runhaskell ex1.hs

Which produces the following output:

Hello World!

If you were able to follow all of that, then congratulations! You are an elite hacker! Your black fedora is in the mail.

I Installed Something Called “Debian Unstable”

So, after weeks of procrastinating, the day finally came; it was time to upgrade Ubuntu. As many of you likely know, Ubuntu has a 6 month release cycle. New versions come out in November and April. The release of Saucy Salamander marked the first time I’ve had to deal with a Linux distro upgrade since I was running Fedora 8 back in 2008 (Not counting a brief encounter with Debian Squeeze just prior to using Ubuntu). As I recall, my attempt to upgrade to Fedora 9 was a disaster. Nothing worked, and it was a huge amount of effort. It was so bad that I decided to cut my losses and just go back to Windows Vista.

Needless to say, I wasn’t terribly excited about upgrading to Saucy. Finally, about a week ago I decided to stop being lazy and just do it. While it wasn’t quite the disaster that Fedora 9 was, I wouldn’t call the upgrade “smooth”. The first thing that I noticed was the fact that I could no longer lock the display. Since my cat likes to perform unauthorized refactoring of my code if I leave the display unlocked, this would not do. I did some googling, and it turns out that Gnome removed gnome-screensaver in Gnome 3.8. Gnome-screensaver controlled, among other things, locking the screen. All of the functionality was rolled into GDM. Ubuntu uses LightDM, so in order to protect my precious codebase I have to either switch it out for GDM, or use a Gnome shell plugin. First, I tried to install GDM, but every time I logged in I would get a popup saying that GDM crashed. I switched back to LightDM and installed the plugin. Everything seemed to be going fine, but things were just a bit more wonky. Every so often, when I’d go to unlock, the screen would freeze. I could just hope it was working and type my password and press enter to unlock it, but I like things to work right.

Not a huge deal though, I thought. I decided that I’d just grin and bear it. However, things continued to come apart. I went about re-compiling DMP Photo Booth and its modules to make sure everything was working correctly with the updated software versions. For the most part it was, but my working splash screen was broken. When shown, the window would pop, but the image on the window would not show. It seemed my call to while (gtk_events_pending()) gtk_main_iteration(); was returning early. In the course of my investigation I decided to open the Glade UI file to make sure everything was right. The only problem? The version of Glade shipped with Saucy has a major bug that causes it to crash when you open a file with a dialog in it. You can read the bug report here.

For me, this was the straw that broke the camel’s back. It was time to try a new distro.

Let’s Meet Our Contestants!

Ubuntu GNOME

I’ve been running Ubuntu for a while now, and have been mostly satisfied with it. I do have some concerns about their direction, but I’m not quite ready to break out the torches and pitch forks. However, I much prefer Gnome 3 to Unity, so I figured it was time to switch to a Gnome-centric distro. Luckily, there is a Ubuntu distro that focuses on Gnome: Ubuntu GNOME. My concern with this is that they seem to have manpower issues. I don’t feel like getting attached, just to have the rug pulled out from under me, so I won’t be using Ubuntu GNOME.

Fedora 20

I feel that it is fair to say that Fedora is to Red Hat as Ubuntu is to Debian. Fedora is an old, mainstream Linux distro that has the financial backing of a large company behind it. It is likely to be around for years to come. Better yet; Fedora is a Gnome distro. Fedora 20 ships with Gnome 3.10, the current latest and greatest.

Back in 2008, I tried to run Ubuntu. Back then, it didn’t “just work”. Fedora did. Maybe it was time to don my Fedora and come home to my first Linux distro. I downloaded the live DVD for Fedora 20, and booted it up. Everything seemed great; Gnome 3.10’s fancy new UI elements were incredibly profound. Mozart and Da Vinci would surely be reduced to tears at the sight of their magnificence. I was sold. I started the installer and got to work. I set my language, hostname, and then went to configure my partitions. …aaaaaaand no hard drives detected. Crud. After some googling around, this seems to be a known issue. The Googler told me that I could disable SELinux and it would work, but no luck. I was told that I could use the non-live image and it would work, but no luck. Well, so much for that idea. I filed my Fedora installation media in the round file and decided what to do next.

Debian Sid

It seems that the cool kids are running Debian these days. I’ve used Debian before, and had good experiences with it (uptime on my Debian Squeeze home server shows 102 days). The one sticking point is how old the software is. That is, old in the stable release; Debian Unstable has up-to-date software. The cool kids assure me that Sid is still more stable than Ubuntu or Fedora, so I decided to give it a shot.

The Installation

Installing Sid is slightly more tricky than Ubuntu or Fedora. Here’s the installation blurb on the Debian Wiki:

Use the stable installer to install a minimal stable system and then change your /etc/apt/sources.list file to testing and do an update and a dist-upgrade, and then again change your /etc/apt/sources.list file to unstable and again do an update and a dist-upgrade. ... If this seems too complicated you should probably not be using unstable.

With those words of encouragement, I set off to work. I downloaded the Debian 7 net install media, and installed. I followed the wizard, setting up the usual things. For partitioning, I formatted my /boot and / partitions, and preserved my /home partition. I spoke about this before in a previous post, but the short answer is that this keeps you from having to back up your data and settings. You should probably still do that stuff in case you do something stupid, but if all goes well you won’t need to.

When the time came to select additional software, I deselected everything. I finished the install and rebooted. The system booted up to the command line, and I logged in and su‘d to root. Now that my Wheezy install was complete, it was time to upgrade to Jessie. This is accomplished by editing /etc/apt/sources.list and changing every instance of the word wheezy to testing. While I was at it, I added contrib and non-free so I could get things like my wifi driver and flash. Next order of business was to install apt-listbugs and apt-listchanges. These two packages change apt-get to warn you of bugs in software, so you don’t blindly install some software that will light your computer on fire. After that:

apt-get update apt-get dist-upgrade

…then I ate lunch. This process will upgrade my system to testing, and it takes a while. After it’s done, I repeated the steps above, replacing all instances of testing with unstable in my sources.list. Additionally I had to delete the lines:

deb http://URL/ testing/updates main deb-src http://URL/ testing/updates main deb http://URL/debian/ testing-updates main deb-src http://URL/debian/ testing-updates main

…these don’t exist in Unstable.

While the apt-get dist-upgrade was running, it was time to watch some TV.

Finally, when apt-get dist-upgrade completed, I had a Debian Sid system. One problem: it was command line only.

A Few More Things

First things first, I needed to set up sudo:

adduser [username] sudo init 6

After the reboot, my user is set up to use sudo.

I had to install some software. First up is Gnome:

sudo apt-get install gnome

This is starts a 1.3 GB download, so I watched some more TV. When that finished, I needed to install my wifi driver so that I could disconnect my temporary cat-5 cable:

sudo apt-get install firmware-iwlwifi

Next up is the Debian laptop applications. This package installs the software that would be installed by selecting the laptop task in tasksel:

sudo apt-get install task-laptop

I rebooted into Gnome. I logged in and connected to my wifi. Since I preserved my /home partition, all my settings are still set up from Ubuntu, so there is very little asthetic configuration to be done.

The gnome package in Debian installs some other things besides Gnome. Among those things is LibreOffice, so I don’t have to worry about that. However, there are a few usability packages to install:

sudo apt-get install flashplugin-nonfree sudo apt-get install synaptic sudo apt-get install pkg-config

At this point I had a basic system set up. Now it is time to make sure DMP Photo Booth still works. Since I preserved my /home, NetBeans is still installed. However, there is no JDK installed. This was an easy fix:

sudo apt-get install openjdk-7-jdk

Now it is time to install the dependencies for DMP Photo Booth:

sudo apt-get install libmagickwand-dev sudo apt-get install libglib2.0 sudo apt-get install libgtk-3-dev sudo apt-get install cups libcups2-dev

Some of the development tools I need still aren’t installed. GCC is installed, but for some reason gdb isn’t. Also, to do work on the trigger, I’ll need avr-gcc:

sudo apt-get install gdb arduino sudo adduser [username] dialout sudo init 6

Finally, I need to install Glade to modify DMP Photo Booth’s UI:

sudo apt-get instal glade

And that’s it!

Impressions

It took me a good half of a day to get it all working, but so far so good. Iceweasel is still a thing, but mozilla.org thinks it’s the latest version of firefox, and my addons still work so I’m not going to worry about it. Plus, weasels rule and foxes drool.

Glade is working now, but DMP Photo Booth’s working screen is still broken. However, I’m beginning to think it never was really working right in the first place.

All in all, it’s been a successful load. 1 week in, and I still don’t miss Ubuntu. Hopefully Sid is good to me, and I’ve found my salvation from getting a new Distro version every 6 months.

Pining for toString()

One of the things that I’ve had difficulty with coming from Java to C is dealing with strings. In Java, string handling is just so easy, they’re nice little objects that keep to themselves and don’t bother anybody. Everybody loves them, and wants to be them. Everybody has a method called toString() that lets them turn into one if you’ll just let them. Want to stick an EnterpriseBaseBeanFactoryFactory into a JLabel? EnterpriseBaseBeanFactoryFactory.toString() and you’re set. Wouldn’t it be nice if we had toString() in C?

About That

We sort of do. Like all things in C, it requires a bit of work, but we can replicate the effect. The function you are looking for is snprintf(), which is in stdio.h. snprintf() is a variadic function that works similarly to printf(). However, instead of printing to stdout, it places the string into a passed-in char *. snprintf() takes at least 3 arguments: a destination char *, the maximum number of bytes to output, and a format string. Following the format string, a variable number of extra arguments corresponding to the format string are passed in, similarly to printf().

Snprintf() does not do any pointer allocation or deallocation, so you should create your char * ahead of time. It can be a stack allocated char array too if you only need a temporary variable. The second argument should be less than or equal to the size of the char *. This size argument prevents snprintf() from writing off the end of your allocated memory.

For Example

Take the following code:

int value = 1000; char to_string[5]; int return_value = snprintf(to_string, 5, "%d", value); printf("Return value: %d, The String: %s", return_value, to_string);

This code creates a char array sized 5, and converts the number 1000. This code produces the following output:

Return value: 4, The String: 1000

…but 1000, is only 4 digits, right? Let’s see what happens if we reduce to_string[]’s size to 4, and the size argument to 4:

int value = 1000; char to_string[4]; int return_value = snprintf(to_string, 4, "%d", value); printf("Return value: %d, The String: %s", return_value, to_string);

…produces an output of:

Return value: 4, The String: 100

Snprintf() wrote “100” into the string and returned 4. What happened? When snprintf() tries to write a number of bytes greater than the limit, it returns the number of bytes that it would have written if the size was large enough. You can use this to test for failures and to determine how big your string needs to be. However, this does not explain why the string was truncated. Snprintf() returned 4, and our limit and array size were both 4, it should have worked, right?

The problem is that we are forgetting the terminating . Snprintf() appends to the end of strings it creates, and size needs to be left over for this null. However, the return value does not account for the terminating null.

What About Sprintf()?

In stdio.h, there is another function that appears to do the same thing: sprintf(). Sprintf() doesn’t take a size_t like snprintf() does. Surely this means that sprintf() does some sort of automatic checking right? No, it doesn’t. Sprintf() will happily write off the end of your passed-in char * and cause all sorts of problems. As we all know, this will result in undefined behavior. It might seem to work. It might segfault. It might even cause lions to emerge from your fridge and eat you. One thing I’m sure we can all agree on is: lions are terrifying. Do yourself a favor, and just use snprintf().

Portability Concerns

Like many things in C, word on the street is that snprintf() behaves differently across different platforms. This blog post was written using GCC and Linux. I can’t promise that snprintf() works exactly the same in Visual Studio, or on some random mainframe or whatever. As always, try it before you buy it.

Configuring NetBeans for GTK Development

Tired of creating console applications in C? Me too. Normally, when it comes time to create a GUI application I turn to good old Java Swing. This is fine and all, but how can I be a proper hoity-toity C programmer who scoffs at the very notion of Java if I can’t even create a proper C GUI app? Clearly, this will not do…

While I do have some experience with QT in the past, I’ve decided to go with GTK. QT is a C++-only toolkit, and I’m not a huge fan of C++. QT also introduces a bunch of magic keywords and requires the use of a special pre-compiler. Meanwhile, GTK is a C library, and requires no fancy pre-compiler. But before I can do anything, I need to configure my environment…

Code Assistance

First, the easy part. You need to make sure you have the GTK development headers installed. If you’re running Ubuntu, this is a simple apt-get:

sudo apt-get install libgtk-3-dev

Now, the hard part. First, we need to launch netbeans. Click Tools -> Options and click C/C++. Click on the Code Assistance tab. Ensure you have the C Compiler tab selected, and the correct toolchain is selected in Tool Collection dropdown. Next, open a new terminal. Enter:

pkg-config --cflags gtk+-3.0

Did you see that gigantic list of paths? You’d better believe that you’re adding all of those to your Include Directories. For each folder, you need to click Add, enter the path in the File Name field, and click Select. When you’re done, your Include Directories should look similar to this:

Click OK when you’re done. Now, it’s time to create a new project. Click File -> New Project… Select C/C++ and Select C/C++ Application. Click Next >. Give your project a name. Ensure that C is selected in the dropdown next to Create Main File, and ensure you have the correct toolchain selected in the Tool Collection dropdown. Click Finish.

Project Properties

Now, it’s time to configure our project properties. Right click your newly created project and click Properties. Click on Build -> C Compiler. Remember in the code completion section when we typed that command and got that gigantic list? Luckily for us, unlike Netbeans, GCC knows what to do with that. In the Compilation Line -> Additional Options field, enter:

`pkg-config --cflags gtk+-3.0`

Note that those are `back qoutes`, not ‘single quotes’. To be clear, it’s the quote located on the ~ button. Next, click Build -> Linker. In the Compilation Line -> Additional Options field, enter:

`pkg-config --libs gtk+-3.0

Note that this line is –libs, not –cflags. If you enter this command, minus backquotes, on the command line, you’ll see it give a list of libraries instead of include paths. When you are done, click OK.

Drumroll…

Open up your main.c source file. At the top of the file, enter:

#include <gtk/gtk.h>

Wait for it…

Wait…
For…
It!

Did Yellow Jaggies appear? Congratulations, you’ve come across the same problem that’s had me troubleshooting for the last 4 hours, and that’s made me give up on GTK several times before. Luckily for you, I have the solution.

Hold Ctrl+Alt and click on include. This should open up the header with the missing inclusion. Find the red jaggies. Open a terminal and enter:

sudo find / -name MISSING_HEADER.h

If the file is not located at the correct spot, try re-installing the library. However, if it is found and in the correct position, then the issue is with code completion. Return to netbeans and click Tools -> Options and click C/C++. Click on the Code Assistance tab. Ensure you have the C Compiler tab selected, and the correct toolchain is selected in Tool Collection dropdown. Locate the offending library, and click Up until it’s at the top of the group of libraries that you just added. Click OK

Did the yellow jaggies go away? Congratulations, you’re done. Otherwise, you get to keep doing this until it works.

When All of That is Done…

Now, it’s time to try it out. For now, you can just copy and paste the Hello World implementation from the GTK+3 Reference Manual. Copy and paste the whole thing, overwriting your existing main function, build it, and run it. If all is well, you should see a window like this:

Pour yourself a glass of wine, and grab a tiny piece of cheese. You are one step closer to lording over the Java Plebians!

%d bloggers like this: