1

I want to make a simple C program that outputs three values, I need the program to output the values ONLY IF the current program is being directly executed and NOT included.

Here is my code:

#define Type "type-of-something"
#define Info "some-basic-info"
#define Todo "something-todo"

To determine whether or not the current script is being imported or directly executed in Python you can do the following:

if __name__ == "__main__":
    pass

I haven't the slightest clue as to how to do this in C but I'm thinking something like this:

#include <stdio.h>
void main(void) {
  if(__name__ == "__main__") {
    printf("%d\n", valueX);
  }
  return;
}

Is something like that possible in C?
If so what is the most efficient way I can go about doing this?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • 5
    A source file with `main` cannot be in a library. – Fiddling Bits Apr 05 '16 at 13:53
  • Only in compile time e.g. #if-defs, also this #if-def must exclude main() {} from obj file or prepare to links error – Vasiliy Soshnikov Apr 05 '16 at 13:57
  • 2
    @FiddlingBits I think there are libraries that are compiled with a `main()`-function that prints usage information if the library is executed as a program. However, if the binary is used as a library, its `main()` is obviously not being called on startup. – EOF Apr 05 '16 at 13:57
  • 1
    P.S. for instance: gcc -DCOMPILE_AS_LIBRARY=1 source.c -D DCOMPILE_AS_LIBRARY will exclude main, etc from compile – Vasiliy Soshnikov Apr 05 '16 at 13:58
  • 1
    @Olaf: And yet that is exactly what for example my libc6 does on Linux. – EOF Apr 05 '16 at 14:16
  • @EOF: Ok, that is interresting. I can't verify on my box right now. Maybe it is a weak symbol? That's currently the only way I can think of how it does not collide. – too honest for this site Apr 05 '16 at 14:34
  • @Olaf: Or maybe, since no program will require a `main()` from a library, the dynamic linker never needs to deal with a `main()` defined in a library, so there is no collision. – EOF Apr 05 '16 at 14:38
  • @EOF: It depends on how the linker works. But agreed, a dynamic linker might be able to make more assumptions than a static linker. I normally don't use dynamic linking for my projects. – too honest for this site Apr 05 '16 at 14:48
  • @Olaf You statically link `libc`? I hope you're not using `glibc` for that, or the size of the executable will be enormous. – EOF Apr 05 '16 at 14:50
  • @EOF - its really not too bad depending on use-case. static linking is fairly normal in embedded software. statically linking `glibc` + busybox will give you most of your system utils in a ~5-10MB binary. Then applications also statically linked against glibc are ~250-500kB for something simple. – Brian McFarland Apr 05 '16 at 14:53
  • @EOF: I did not state I link libc. That would be quite nonsense on bare-metal embedded systems. – too honest for this site Apr 05 '16 at 14:53
  • @BrianMcFarland: The systems I use normally don't have 5MiB of memory in total. Even less program Flash. – too honest for this site Apr 05 '16 at 14:54
  • Sidebar about static linking aside: The real problem with trying to accomplish what OP is going for is that ELF and PE both use different formats for libraries vs executables. As far as I can tell, its impossible for your final binary to be *both*, like a Python module. – Brian McFarland Apr 05 '16 at 14:55
  • @Olaf - I'm quite familiar with working in MCU environments where you might not link in any `libc` functionality, just saying that static linking is not unheard of with a full-blown OS either. – Brian McFarland Apr 05 '16 at 14:58
  • @BrianMcFarland: `file ./libc-2.19.so` -> `./libc-2.19.so: ELF 64-bit LSB shared object[...]`. `./libc-2.19.so` -> `GNU C Library (Ubuntu EGLIBC 2.19-0ubuntu6.7) stable release version 2.19, by Roland McGrath et al. [...]`. There's a question about it http://stackoverflow.com/q/6899361/3185968 and a dupe-chain. – EOF Apr 05 '16 at 14:58
  • @Olaf - In the context of an purpose built Linux system, static linking can actually *reduce* your binary footprint. You could build a fully functional Linux system with only one application binary (/init) and get the entire kernel + initramfs image down to ~2MB, maybe less. Fast load times are perfect example where this can be useful, e.g. where you need userspace running within 1-2 seconds of applying power. The appearance of "instant on" (e.g. phones) can be done with low current modes, but sometimes they aren't low enough current and you really do need to cold boot that fast. – Brian McFarland Apr 05 '16 at 15:24
  • I've seen projects were if static linking shrinks an initramfs enough to shave 100ms off the boot time, it would absolutely be done. – Brian McFarland Apr 05 '16 at 15:25
  • @BrianMcFarland: Thanks for the infos. They are very much appreciated for a project I'm currently thinking of. I still have to do some research, but at least that give me some orientation and shows that some of the goals are indeed possible. – too honest for this site Apr 05 '16 at 16:00

2 Answers2

0

I'd go for something like this, if you want it simple stupid:

#include <stdbool.h>

bool as_library = true;

int main(int argc, char ** argv) {
  as_library = false;
  // ...
  return 0;
}

Since when you're code is compiled and used as program, that main will be called, then that boolean will be set accordingly.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
0

This is a pretty contrived problem for which I struggle to see any real world application. That said, the following more or less works on Ubuntu 14.04 with gcc 4.8.4. Your mileage may vary.

This uses pragma weak to define main as a weak symbol.

Note that you still cannot execute the resulting mylib.so directly because (at least on Linux) there are two different ELF formats for executable files and dynamically linked libraries.

I tried compiling the "shared library" with -fPIC, but without -shared to yield an executable ELF, but then you cannot get ld to treat it as a shared library. dlopen doesn't work either.

So I think this is the best you can do on *nix + gcc. This is going to be compiler specific, so who knows what you might do on windows.

Makefile:

all: test1 test2

#test1 links in mylib.so the "normal" way.
# -Wl,-rpath . is used to search the current directry for mylib.so
# at runtime so the library doesn't have to be "installed".
test1: test.c mylib.so
    gcc -Wl,-rpath . -o $@ $^

#test2 builds an executable out of *just* the library, no other source.    
test2: ./mylib.so
    gcc -Wl,-rpath . -o $@ $^

# Target to compile the .so file.
mylib.so: lib.c
    gcc -shared -o $@ -fPIC $^

# cleanup target.
.PHONY: clean
clean:
    rm -f test1 test2 mylib.so

test.c:

extern void say_hello(const char * msg);

/* pragma weak is the real magic here that allows the library to 
   contain a 'main' -OR- allow application code to define its own
   main. */
#pragma weak main
int main(int argc, char**argv)
{
  say_hello("hello from test main\n");
  return 0;
}

lib.c:

#include <stdio.h>

/* the shared library function used by both programs */
void say_hello(const char * msg)
{
  puts(msg);
}

int main(int argc, char**argv)
{
  say_hello("hi from library's main\n");
}
Brian McFarland
  • 9,052
  • 6
  • 38
  • 56