[[:improve]]
Viele Eigenschaften der Programmiersprache C basieren aufgrund der Nähe zu [[coding:assembly|Assembly]]. Siehe auch [[coding:cpp|C++]]/[[coding:csharp|C#]].
{{winapi_hwnd.pdf||Hwnd}}
=====Datentypen=====
====Integer====
// testValue
unsigned long long testValue = 0xFFFFFFFFFFFFFFFF; // 18446744073709551615
// 1 byte -> [0-255] or [0x00-0xFF]
unsigned char numberChar = testValue; // 255
// 2 bytes -> [0-65535] or [0x0000-0xFFFF]
unsigned short numberShort = testValue; // 65535
// 4 bytes -> [0-4294967295] or [0x00000000-0xFFFFFFFF]
unsigned int numberInt = testValue; // 4294967295
// 4 bytes -> [0-4294967295] or [0x00000000-0xFFFFFFFF]
unsigned long numberLong = testvalue;
// 8 bytes -> [0-18446744073709551615] or [0x0000000000000000-0xFFFFFFFFFFFFFFFF]
unsigned long long numberLongLong = testValue; // 18446744073709551615
printf("%u %d %u %lu %llu", numberChar, numberShort, numberInt, numberLong, numberLongLong);
====Float====
=====Strtok=====
#include
int main()
{
char buf[] = "Hello world, how are you?";
char *token = strtok(buf, " ");
while(token != NULL) {
printf("token: %s\n", token);
token = strtok(NULL, " ");
}
}
Nested strtok_r: https://stackoverflow.com/questions/4693884/nested-strtok-function-problem-in-c
=====Statische Variablen=====
// Eine statische Variable innerhalb einer Funktion behält ihren Wert auch zwischen mehreren Aufrufen.
void foo() {
int a = 10;
static int sa = 10;
a += 5;
sa += 5;
printf("a = %d, sa = %d\n", a, sa);
}
int main() {
int i;
for (i = 0; i < 10; ++i) foo();
}
=====Pointer=====
Siehe [[:c_pointer|Pointer in C]].
int array[5]; // Declares 5 contiguous integers
int *ptr = array; // Arrays can be used as pointers
ptr[0] = 1; // Pointers can be indexed with array syntax
*(array + 1) = 2; // Arrays can be dereferenced with pointer syntax
*(1 + array) = 3; // Pointer addition is commutative
2[array] = 4; // Subscript operator is commutative
char a, b; // 2 chars = 2 bytes
char *zeiger; // einen (char) zeiger
zeiger = &a; // zeiger beinhaltet adresse von a
*zeiger = 'A'; // schreibe ein 'A' an die im Zeiger gespeicherte Adresse von a
printf("Kapitel %c\n", a);
zeiger = &b; // zeiger beinhaltet adresse von b
*zeiger = 'B'; // schreibe ein 'B' an die im Zeiger gespeicherte Adresse von b
printf("Kapitel %c\n", b);
// Pointer auf eine Funktion
void func(int *i) {
(*i)++; // *i++ geht nicht! Siehe Pointer Arithmetik
}
int main() {
void (*func_ptr)(int*) = &func;
int i = 0;
(*func_ptr)(&i);
printf("%d", i);
}
=====Pass by reference=====
// pass a pointer
void modify(char *s){
s[0] = 'g';
}
int main(){
char name[] = "New Holland";
char *p_name = name;
modify(p_name);
printf("%s\n", name);
}
// pass the address of a pointer
void modify(char **s){
char *new_name = "Old Holland";
*s = new_name;
}
int main(){
char name[] = "New Holland";
char *p_name = name;
modify(&p_name);
printf("%s\n", name);
}
=====Constants=====
In compiled code there are several segments.
* Code, Segment (for the actual rom code)
* Data Segment (for initialised global and static variables)
* Stack segment (local variables, return address, ..)
* Heap segment (all dynamic allocations)
* BSS (uninitialised global and static variables)
Every segment has a read only region where constants are stored. The compiler - and only the compiler - has to decide in which segment a variable get stored. And then, if the variable is a const it is stored in the r/o region of that specific segment.
* A local const int is stored in the r/o region of stack segment.
* A global const int is stored in the r/o region of data segment.
* Any uninitialised const int is stored in the r/o BSS segment.
#include
int main() {
const int a = 10;
int b = 20;
const int *ptr = &a;
printf("ptr: %d\n", *ptr);
// error!!!
*ptr = b;
ptr = &b;
printf("ptr: %d\n", *ptr);
}
See also [[coding:cpp#constants|constants in CPP]]
=====Binary Operations=====
void print(int n) {
for (int i = 0; i < 8; i++) {
printf("%d", !!((n << i) & 0x80));
}
}
int main() {
unsigned int a = 44; /* 0010 1100 */
unsigned int b = 13; /* 0000 1101 */
print(a);
printf(" => a\n");
print(b);
printf(" => b\n--------\n");
int c = 0;
c = a & b;
print(c); printf(" => a & b\n");
c = a | b;
print(c); printf(" => a | b\n");
c = a ^ b;
print(c); printf(" => a ^ b\n");
c = ~a;
print(c); printf(" => ~a\n");
c = a << 2;
print(c); printf(" => a << 2\n");
c = a >> 2;
print(c); printf(" => a >> 2");
}
& (AND)
1 & 1 == 1
1 & 0 == 0
0 & 1 == 0
0 & 0 == 0
00110010 - b
& 00010000 - & 0x10
----------
00010000 - result
| (OR)
1 | 1 == 1
1 | 0 == 1
0 | 1 == 1
0 | 0 == 0
00110010 - b
| 00000100 - | 0x04
----------
00110110 - result
^ (XOR)
1 ^ 1 == 0
1 ^ 0 == 1
0 ^ 1 == 1
0 ^ 0 == 0
00110010 - b
^ 00011000 - ^ 0x18
----------
00101010 - result
00101010 - b
^ 00011000 - ^ 0x18
----------
00110010 - result
~ (Inversion, One complement)
00000011 - 0x03
11111100 - ~0x03 b
<< >> (Bit shifting)
00001100 - b
00110000 - b << 2
00000011 - b >> 2
Siehe [[:logikgatter|Wahrheitstabelle]]. [[https://www.youtube.com/watch?v=F8kx56OZQhg|OneLoneCoder bitwise operations]]
=====Memory=====
Initialisieren
int main() {
char str[20];
// Setzen aller Elemente des Arrays auf 'A'
memset(str, 'A', sizeof(str));
printf("Initialized string: %s\n", str);
return 0;
}
Kopieren
int main() {
char source[] = "Hello, World!";
char destination[20];
// Kopieren des Inhalts von source nach destination
memcpy(destination, source, sizeof(source));
printf("Copied string: %s\n", destination);
return 0;
}
Vergleichen
int main() {
char str1[] = "abc";
char str2[] = "abd";
// Vergleichen der beiden Strings
int result = memcmp(str1, str2, sizeof(str1));
if (result == 0) {
printf("Strings are equal.\n");
} else if (result < 0) {
printf("String 1 is less than String 2.\n");
} else {
printf("String 1 is greater than String 2.\n");
}
return 0;
}
=====Memory allocation=====
''malloc'' and ''calloc'' are almost the same except ''calloc'' zerores out the block. malloc takes only the size as arg, ''calloc'' need size and type. ''realloc'' is king.
int main() {
char *ptr = (char *)malloc(1024 * sizeof(char));
char buf1[1024] = {'a'};
strcat(ptr, buf1);
ptr = realloc(ptr, 1024 * sizeof(char));
char buf2[1024] = {'B'};
strcat(ptr, buf2);
printf("%s", ptr);
free(ptr);
}
=====Buffer=====
#include
#include
#define SIZE 64
unsigned char memory[SIZE];
void print_memory() {
printf("\n\t00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15");
for(int i = 0; i < SIZE; i++) {
if(i % 16 == 0)
printf("\n%04d:\t", i);
printf("%02x ", memory[i]);
}
printf("\n");
}
int main() {
int offset = 0;
memset(memory, SIZE, 0);
char str[] = "Hello world";
memcpy(memory + offset, &str, strlen(str));
offset += strlen(str);
print_memory();
float f = 3.14159f;
memcpy(memory + offset, &f, sizeof(float));
//offset += sizeof(float);
print_memory();
float tmp;
memcpy(&tmp, &memory[offset], sizeof(float));
printf("%f", tmp);
return 1;
}
=====Files=====
FILE *f;
f = fopen("test.txt", "w");
char msg[] = "Hello world";
fwrite(msg, sizeof(msg), 1, f);
fclose(f);
f = fopen("test.txt", "r");
fseek(f, 0L, SEEK_END);
int len = ftell(f);
rewind(f);
char c, buffer[len];
int i = 0;
while( fread(&c, sizeof(char), 1, f) > 0 ) buffer[i++] = c;
fclose(f);
buffer[i] = '\0';
printf("%s", buffer);
f = fopen("test.txt", "r");
char ch;
while((ch = fgetc(f)) != EOF) printf("%c", ch);
fclose(f);
f = fopen("test.txt", "r");
char *line = NULL, read;
size_t len = 0;
while((read = getline(&line, &len, f)) > -1) printf("(%d) %s", read, line);
std::ifstream f("test.txt");
std::string data, line;
while(std::getline(f, line))
data += line;
std::cout << data;
Read 4 chars as a single int
FILE *f = fopen("test.txt", "rw");
char msg[] = {0x41,0x42,0x43,0x44};
fwrite(&msg, 1, sizeof(char), f);
int *buffer;
fread(&buffer, sizeof(int), 1, f);
fclose(f);
printf("%d", buffer); // 0x41424344 = 1145258561
Piping in windows
#include
#include
int main(void){
char psBuffer[128];
FILE *pPipe;
if((pPipe = _popen("curl https://orf1.mdn.ors.at/out/u/orf1/q4a/manifest.m3u8", "rt")) == NULL ) exit(1);
while(fgets(psBuffer, 128, pPipe)) {
printf(psBuffer);
}
if (feof( pPipe)) printf("\nreturn %d\n", _pclose(pPipe));
else printf( "Failed\n");
}
=====Data Structures=====
====Arrays====
#include
int main() {
// Erstellen eines Arrays mit 5 Elementen vom Typ int
int array[5] = {1, 2, 3, 4, 5};
// Zugriff auf Elemente des Arrays
printf("Element 0: %d\n", array[0]);
printf("Element 3: %d\n", array[3]);
return 0;
}
====Struct====
struct Data {
int i;
float f;
char *str;
};
int main( ) {
// like this
struct Data data = {10, 2.5};
// or like this
struct Data data;
data.i = 10;
data.f = 2.5;
data.str = "Hello world";
printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf( "data.str : %s\n", data.str);
}
Recursive Structure
typedef struct Node {
char *value;
struct Node* left;
struct Node* right;
} Node;
Structure in anderer Structure
struct Details {
char *name;
};
struct Entry {
int id;
struct Details details;
};
int main() {
struct Entry entry = {1, "Manuel"};
printf("id: %d\n", entry.id);
printf("name: %s\n", entry.details.name);
}
Structures mit void* Pointern
typedef void (*Callback)();
struct Table {
int id;
char *type;
void *val;
Callback callback;
};
void myFunction(const char *s) {
printf("%s", s);
}
int main() {
struct Table *t = malloc(sizeof(struct Table));
t->id = 1;
t->type = "string";
char s[] = "Hello world, heheh";
t->val = &s;
t->callback = myFunction;
t->callback(t->val);
}
====Linked List====
#include
#include
#include
#include
struct node {
int data;
int key;
char *c;
struct node *next;
};
struct node *head = NULL;
struct node *current = NULL;
//display the list
void printList() {
struct node *ptr = head;
printf("\n[ ");
//start from the beginning
while(ptr != NULL) {
printf("(%d,%d) ",ptr->key,ptr->data);
ptr = ptr->next;
}
printf(" ]");
}
//insert link at the first location
void insertFirst(int key, int data) {
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
link->data = data;
//point it to old first node
link->next = head;
//point first to new first node
head = link;
}
//delete first item
struct node* deleteFirst() {
//save reference to first link
struct node *tempLink = head;
//mark next to first link as first
head = head->next;
//return the deleted link
return tempLink;
}
//is list empty
bool isEmpty() {
return head == NULL;
}
int length() {
int length = 0;
struct node *current;
for(current = head; current != NULL; current = current->next) {
length++;
}
return length;
}
//find a link with given key
struct node* find(int key) {
//start from the first link
struct node* current = head;
//if list is empty
if(head == NULL) {
return NULL;
}
//navigate through list
while(current->key != key) {
//if it is last node
if(current->next == NULL) {
return NULL;
} else {
//go to next link
current = current->next;
}
}
//if data found, return the current Link
return current;
}
//delete a link with given key
struct node* delete(int key) {
//start from the first link
struct node* current = head;
struct node* previous = NULL;
//if list is empty
if(head == NULL) {
return NULL;
}
//navigate through list
while(current->key != key) {
//if it is last node
if(current->next == NULL) {
return NULL;
} else {
//store reference to current link
previous = current;
//move to next link
current = current->next;
}
}
//found a match, update the link
if(current == head) {
//change first to point to next link
head = head->next;
} else {
//bypass the current link
previous->next = current->next;
}
return current;
}
void sort() {
int i, j, k, tempKey, tempData;
struct node *current;
struct node *next;
int size = length();
k = size ;
for ( i = 0 ; i < size - 1 ; i++, k-- ) {
current = head;
next = head->next;
for ( j = 1 ; j < k ; j++ ) {
if ( current->data > next->data ) {
tempData = current->data;
current->data = next->data;
next->data = tempData;
tempKey = current->key;
current->key = next->key;
next->key = tempKey;
}
current = current->next;
next = next->next;
}
}
}
void reverse(struct node** head_ref) {
struct node* prev = NULL;
struct node* current = *head_ref;
struct node* next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}
void main() {
insertFirst(1,10);
insertFirst(2,20);
insertFirst(3,30);
insertFirst(4,1);
insertFirst(5,40);
insertFirst(6,56);
printf("Original List: ");
//print list
printList();
while(!isEmpty()) {
struct node *temp = deleteFirst();
printf("\nDeleted value:");
printf("(%d,%d) ",temp->key,temp->data);
}
printf("\nList after deleting all items: ");
printList();
insertFirst(1,10);
insertFirst(2,20);
insertFirst(3,30);
insertFirst(4,1);
insertFirst(5,40);
insertFirst(6,56);
printf("\nRestored List: ");
printList();
printf("\n");
struct node *foundLink = find(4);
if(foundLink != NULL) {
printf("Element found: ");
printf("(%d,%d) ",foundLink->key,foundLink->data);
printf("\n");
} else {
printf("Element not found.");
}
delete(4);
printf("List after deleting an item: ");
printList();
printf("\n");
foundLink = find(4);
if(foundLink != NULL) {
printf("Element found: ");
printf("(%d,%d) ",foundLink->key,foundLink->data);
printf("\n");
} else {
printf("Element not found.");
}
printf("\n");
sort();
printf("List after sorting the data: ");
printList();
reverse(&head);
printf("\nList after reversing the data: ");
printList();
}
* Zentut Linked Lists http://www.zentut.com/c-tutorial/c-linked-list/
* https://www.tutorialspoint.com/data_structures_algorithms/linked_list_program_in_c.htm
* https://stackoverflow.com/questions/50223927/c-how-to-read-in-a-linked-list-from-a-binary-file (BINARY)
====Hash Table====
#include
#include
#define SIZE 10
struct Node {
int key;
int value;
struct Node* next;
};
struct Node* hashTable[SIZE];
int hashFunction(int key) {
return key % SIZE;
}
void insert(int key, int value) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->key = key;
newNode->value = value;
newNode->next = NULL;
int index = hashFunction(key);
if (hashTable[index] == NULL) {
hashTable[index] = newNode;
} else {
struct Node* current = hashTable[index];
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
}
int search(int key) {
int index = hashFunction(key);
struct Node* current = hashTable[index];
while (current != NULL) {
if (current->key == key) {
return current->value;
}
current = current->next;
}
return -1;
}
int main() {
// Initialisierung der Hash-Tabelle
for (int i = 0; i < SIZE; i++) {
hashTable[i] = NULL;
}
// Einfügen von Elementen
insert(1, 10);
insert(2, 20);
insert(11, 30);
// Suche nach einem Schlüssel
int value = search(2);
if (value != -1) {
printf("Value found: %d\n", value);
} else {
printf("Value not found.\n");
}
return 0;
}
====Stack====
#include
#include
#define MAX_SIZE 100
struct Stack {
int items[MAX_SIZE];
int top;
};
void initialize(struct Stack* stack) {
stack->top = -1;
}
int isEmpty(struct Stack* stack) {
return stack->top == -1;
}
int isFull(struct Stack* stack) {
return stack->top == MAX_SIZE - 1;
}
void push(struct Stack* stack, int item) {
if (isFull(stack)) {
printf("Stack overflow!\n");
return;
}
stack->items[++stack->top] = item;
}
int pop(struct Stack* stack) {
if (isEmpty(stack)) {
printf("Stack underflow!\n");
return -1;
}
return stack->items[stack->top--];
}
int main() {
struct Stack stack;
initialize(&stack);
push(&stack, 1);
push(&stack, 2);
push(&stack, 3);
printf("Popped: %d\n", pop(&stack));
printf("Popped: %d\n", pop(&stack));
printf("Popped: %d\n", pop(&stack));
return 0;
}
====Queue====
#include
#include
#define MAX_SIZE 100
struct Queue {
int items[MAX_SIZE];
int front;
int rear;
};
void initialize(struct Queue* queue) {
queue->front = -1;
queue->rear = -1;
}
int isEmpty(struct Queue* queue) {
return queue->front == -1;
}
int isFull(struct Queue* queue) {
return (queue->rear + 1) % MAX_SIZE == queue->front;
}
void enqueue(struct Queue* queue, int item) {
if (isFull(queue)) {
printf("Queue overflow!\n");
return;
}
if (isEmpty(queue)) {
queue->front = 0;
queue->rear = 0;
} else {
queue->rear = (queue->rear + 1) % MAX_SIZE;
}
queue->items[queue->rear] = item;
}
int dequeue(struct Queue* queue) {
if (isEmpty(queue)) {
printf("Queue underflow!\n");
return -1;
}
int item = queue->items[queue->front];
if (queue->front == queue->rear) {
queue->front = -1;
queue->rear = -1;
} else {
queue->front = (queue->front + 1) % MAX_SIZE;
}
return item;
}
int main() {
struct Queue queue;
initialize(&queue);
enqueue(&queue, 1);
enqueue(&queue, 2);
enqueue(&queue, 3);
printf("Dequeued: %d\n", dequeue(&queue));
printf("Dequeued: %d\n", dequeue(&queue));
printf("Dequeued: %d\n", dequeue(&queue));
return 0;
}
=====Signed unsigned=====
By default an (ANSI C) integer is signed.
int a = 5;
int b = -10;
(a>b) ? puts("a>b") : puts("-");
unsigned int c = 5;
int d = -10;
(c>d) ? puts("c>d") : puts("-");
printf("%08x %08x %08x %08x", a,b,c,d);
=====Makros=====
* The ## operator takes two separate tokens and pastes them together to form a single token.
* The # Operator will "stringify" the following token.
* siehe http://www.eckart-winkler.de/computer/c/makros.htm
#define f(a,b) a##b // strcat
#define h(a) g(a) // exec
#define g(a) #a // stringify
int main() {
printf("%s\n",h(f(1,2)));
printf("%s\n",g(f(1,2)));
return 0;
}
=====Preprocessing=====
Gilt auch für [[coding:cpp|CPP]]. Compileranweisungen vor dem eigentlichen Kompilierung ausführen. Dabei werden z.B makros durch den eigentlichen Code ersetzt.
Das folgende Programm mit ''gcc -E'' vorkompiliert
#define DEFINE_LL_NODE(CONCRETE_TYPE) \
struct node_of_ ## CONCRETE_TYPE { \
CONCRETE_TYPE data; struct node_of_ ## CONCRETE_TYPE *next; \
}; \
#define DECLARE_LL_NODE(CONCRETE_TYPE, VARIABLE_NAME) \
struct node_of_ ## CONCRETE_TYPE VARIABLE_NAME;
/* Declarations for types int and char */
DEFINE_LL_NODE(int)
DEFINE_LL_NODE(char)
int main (void)
{
/* Declaration of instances of each type. */
DECLARE_LL_NODE (int, foo)
DECLARE_LL_NODE (char, bar)
/* And you can then use these instances. */
foo.data = 1;
foo.next = NULL;
bar.data = 'c';
bar.next = NULL;
}
erzeugt ein Object file das so aussieht.
# 1 "main.c"
# 1 ""
# 1 ""
# 1 "main.c"
# 10 "main.c"
struct node_of_int { int data; struct node_of_int *next; };
struct node_of_char { char data; struct node_of_char *next; };
int main (void)
{
struct node_of_int foo;
struct node_of_char bar;
foo.data = 1;
foo.next = NULL;
bar.data = 'c';
bar.next = NULL;
}
=====Stdarg=====
Pass multiple (unknown at runtime) parameters to a function.
#include
// define known parameters, everything after ",..." must be the same Datatype!!!
void myfunc(const char *str, ...) {
va_list list;
va_start(list, str);
while(str) {
printf("%s", str);
str = va_arg(list, const char *);
}
va_end(list);
}
int main() {
char *a = "a";
char *b = "b";
myfunc(a,b,NULL);
}
=====Classes=====
typedef struct Class Class;
struct Class {
double width, height; /* Variables */
double (*area)(Class *_class); /* Function pointer */
};
/* Function */
double calc(Class *_class) {
return _class->width * _class->height;
}
/* Constructor */
Class _Class() {
Class s;
s.width = 1;
s.height = 1;
s.area = calc;
return s;
}
int main() {
Class s1 = _Class();
s1.width = 4;
s1.height = 5;
printf("width = %f\n", s1.width);
printf("height = %f\n", s1.height);
printf("area = %f\n", s1.area(&s1));
};
#include
typedef struct {
void (*someMethod)(void);
} Test;
void hello(void) {
printf("hello");
}
void world(void) {
printf("world");
}
int main(void) {
Test test;
test.someMethod = "hello";
test.someMethod();
test.someMethod = "world";
test.someMethod();
}
See also [[coding:cpp#classes|classes in CPP]]
=====Inline Assembly=====
GCC
#include
int main() {
int a = 5, b = 10, result;
asm volatile (
"movl %1, %%eax;" // Move a into EAX register
"movl %2, %%ebx;" // Move b into EBX register
"addl %%ebx, %%eax;" // Add EBX to EAX
"movl %%eax, %0;" // Move the result back to variable result
: "=r" (result) // Output operand
: "r" (a), "r" (b) // Input operands
: "%eax", "%ebx" // Clobbered registers
);
printf("Result: %d\n", result);
return 0;
}
Visual C++
#include
int main() {
int a = 5, b = 10, result;
__asm {
mov eax, a // Move a into EAX register
mov ebx, b // Move b into EBX register
add eax, ebx // Add EBX to EAX
mov result, eax // Move the result back to variable result
}
printf("Result: %d\n", result);
return 0;
}
[[https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html|Extended inline ASM]]
=====Resources=====
Datei resource.rc erstellen
#ifndef RESOURCE_RC_INCLUDED
#define RESOURCE_RC_INCLUDED
MAINICON ICON "icon.ico"
#endif
und windres resource.rc resource.o
aufrufen.
Optional, in C/CPP nochmal definieren
#define MAINICON 101
Danach kann man das Programm wie üblich kompilieren.
gcc prog.c resource.o -o prog.exe
=====Processes=====
#include
int main(int argc, char *argv[]) {
FILE *fp = popen("ipconfig", "w");
int i = 0;
char line[1024];
while (fgets(line, sizeof(line), fp) != NULL) {
printf("%s\n", line);
}
pclose(fp);
return 0;
}
=====Signal=====
#include
void catch_function(int sig) {
exit(EXIT_FAILURE);
}
signal(SIGINT, catch_function);
=====declspec=====
extern "C"
{
__declspec(dllexport) int add(int a,int b) {
return a+b;
}
__declspec(dllexport) int subtract(int a,int b) {
return a-b;
}
}
=====Libraries und Shared objects=====
// windows
__declspec(dllexport) char *myfunc() {
return "myfunc called";
}
// linux
__attribute__ ((visibility ("default"))) char *myfunc() {
return "myfunc called";
}
Diese Library Datei kompiliert man mit dem -c Parameter.
// -fPIC für positionsunabhängigen Code
// Windows dynamic
gcc -c test.c -o test.o
gcc -shared test.o -o test.dll
gcc main.c -o main -L. -ljail
// Windows static
gcc -c -static test.c
ar rcs test.a test.o
gcc main.c -o main test.a
// Linux dynamic
gcc -c test.c
gcc -shared test.o -o libTest.so // with lib prefix
gcc main.c -o main -L. -lTest // without lib prefix
// Linux static
gcc -c test.c -o test.o
ar crf libTest.a test.o // with lib prefix
gcc main.c -o main -L. -lTest // without lib prefix
#include
#include
#ifdef _WIN32
#include
#else
#include
#endif
#ifdef _WIN32
typedef HANDLE lib_t;
#else
typedef void* lib_t;
#endif
lib_t MyLoadLib(const char* lib) {
#ifdef _WIN32
return LoadLibraryA(lib);
#else
return dlopen(lib, RTLD_LAZY);
#endif
}
void MyUnloadLib(lib_t lib) {
#ifdef _WIN32
FreeLibrary(lib);
#else
dlclose(lib);
#endif
}
void* MyLoadProc(lib_t lib, const char* proc) {
#ifdef _WIN32
return GetProcAddress(lib, proc);
#else
return dlsym(lib, proc);
#endif
}
int main(int argc, char **argv) {
lib_t myLib = NULL;
myLib = MyLoadLib("./myLib.so");
void *funcname;
funcname = "init";
void *(*func_ptr)() = MyLoadProc(myLib, funcname);
char *result;
result = (*func_ptr)();
printf("%s", result);
MyUnloadLib(myLib);
return 0;
}
=====Links=====
* http://www.gowrikumar.com/c/index.php
* https://de.wikibooks.org/wiki/C-Programmierung:_Komplexe_Datentypen
* http://manpages.ubuntu.com/manpages/bionic/man1/elfrc.1.html
* [[https://www.quora.com/How-is-a-hash-table-different-to-a-linked-list-or-an-array|Linked List, Hashtable, Array Comparision]]
=====More=====
* Managed Assembly https://stackoverflow.com/questions/973939