PDA

View Full Version : C Plugins



Dgby714
08-11-2011, 09:19 PM
C Plugins

For this tutorial you will need a C compiler.
I will also include some information on a simple Makefile for C projects.

You will want a reliable way to backup your work!! Ex: GitHub (https://github.com/), googlecode (http://code.google.com/)

There is a zip at the end of this post with all the files needed to start your C plugins (Doesn't include a C compiler or make)

Here is a template for main.c (Can be renamed to anything with a c extension)

#include <main.h>
#include <string.h>

static __stdcall int a(void)
{
return 42;
}

static __stdcall int GetFuncCount(void)
{
return 1;
}

static __stdcall int GetFuncInfo(int x, void **addr, char **def)
{
switch (x) {
case 0:
*addr = (void *)&a;
strcpy(*def, "function a(): LongInt;");
break;
default:
x = -1;
}
return x;
}

and main.h
Note there is a little magic here to get rid of stdcall name mangling.

#ifndef __MAIN_H_
#define __MAIN_H_

static __stdcall int a(void);
static __stdcall int GetFuncCount(void);
static __stdcall int GetFuncInfo(int x, void **addr, char **def);

int GetFunctionCount(void) __attribute__((alias("GetFuncCount@0")));
int GetFunctionInfo(int x, void **addr, char **def) __attribute__((alias("GetFuncInfo@12")));

#endif

Now you can ether decide on a Makefile or a simple sh/bat file.

Your simple bat/sh file will look something like this.

gcc -I. -c main.c -o main.o
gcc -shared -o libTest.dll main.o

You can also go the Makefile route.
For this method I ask you put all *.c files in src/
and all *.h files in includes/


.PHONY: all build clean dist todolist

PROJECT=cplugin4simb
CC=gcc

EXT=.so
ifeq ($(OS),Windows_NT)
EXT=.dll
endif

AUXFILES := Makefile README COPYING $(PROJECT)$(EXT)
PROJDIRS := src includes
SRCFILES := $(shell find $(PROJDIRS) -type f -name "*.c")
HDRFILES := $(shell find $(PROJDIRS) -type f -name "*.h")
OBJFILES := $(patsubst src/%.c,build/%.o,$(SRCFILES))
DEPFILES := $(patsubst src/%.c,build/%.d,$(SRCFILES))
SRCFILES := $(SRCFILES)
ALLFILES := $(SRCFILES) $(HDRFILES) $(AUXFILES)

WARNINGS := -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align \
-Wwrite-strings -Wmissing-prototypes -Wmissing-declarations \
-Wredundant-decls -Wnested-externs -Winline -Wno-long-long \
-Wuninitialized -Wconversion -Wstrict-prototypes
CFLAGS := -g -std=c99 -O -I./includes -c $(WARNINGS)

all: clean build

build: $(PROJECT)$(EXT)

$(PROJECT)$(EXT): $(OBJFILES)
@$(CC) -shared -o $(PROJECT)$(EXT) $(OBJFILES)

%/.ph:
@mkdir -p $(@D)
@touch $@

build/%.o: src/%.c build/.ph
@$(CC) $(CFLAGS) $< -o $@

clean:
-@$(RM) $(wildcard $(PROJECT).tar.gz $(PROJECT)$(EXT))
-@$(RM) -r build

dist:
@tar czf $(PROJECT).tar.gz $(ALLFILES)

todolist:
-@for file in $(SRCFILES); do fgrep -H -e TODO -e FIXME $$file; done; true


Note this makefile will build your dll with ALL c files in src/ no need to change anything.


If you notice anything weird or wrong, please don't hesitate to ask questions.

i luffs yeww
08-11-2011, 09:20 PM
Good

Dgby714
08-11-2011, 09:21 PM
Holy crap luffs, you're fast.... Only 1min after I made the thread...

i luffs yeww
08-11-2011, 09:22 PM
Mind reader. Not super informative, but whatever. :p

nielsie95
08-11-2011, 09:23 PM
Cool :) How do you work with strings? Pass them as PChar?

Dgby714
08-11-2011, 09:24 PM
Cool :) How do you work with strings? Pass them as PChar?

Yes, tho PascalScript's string does work as a PChar as well you just have to remember to add a #0 too the end.

Echo_
08-12-2011, 04:06 PM
Really nice tutorial, I do have one question. What are the @0 and @12 for at the end of the strings in the header file? ("GetFuncCount@0" and "GetFuncInfo@12")

Dgby714
08-28-2011, 09:25 AM
Really nice tutorial, I do have one question. What are the @0 and @12 for at the end of the strings in the header file? ("GetFuncCount@0" and "GetFuncInfo@12")

It is stdcall name mangling. It is how much of space the parameters take up, some compilers also add a underscore to the begging of the function.

say

int __stdcall a(int b);

externally will look like

a@4 or _a@4

where as

int __stdcall a(void); (This has no parameters)

will look like

a@0 or _a@0

Frement
08-28-2011, 11:53 AM
It is stdcall name mangling. It is how much of space the parameters take up, some compilers also add a underscore to the begging of the function.

say

int __stdcall a(int b);

externally will look like

a@4 or _a@4

where as

int __stdcall a(void); (This has no parameters)

will look like

a@0 or _a@0

So it doesn't count space? "int b" becomes basically "intb"?

Dgby714
08-28-2011, 12:04 PM
So it doesn't count space? "int b" becomes basically "intb"?

You are quite lost lol...

I ment it show the size of all the parameters.

An int is 4 bytes long.

so a function with only 1 parameter that is an int gets @4
Where as a function with 2 parameters both int gets @8

pointers are also 4 bytes long.

so take a look at

static __stdcall int GetFuncInfo(int x, void **addr, char **def);

it has 3 parameters

a int 4 bytes
a pointer 4 bytes
another pointer 4 bytes

that means it will be

GetFuncInfo@12

Echo_
08-28-2011, 01:03 PM
It is stdcall name mangling. It is how much of space the parameters take up, some compilers also add a underscore to the begging of the function.

say

int __stdcall a(int b);

externally will look like

a@4 or _a@4

where as

int __stdcall a(void); (This has no parameters)

will look like

a@0 or _a@0

Thanks for clearing that up :D