-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathtransform.c
140 lines (109 loc) · 4.18 KB
/
transform.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Generated_C.h"
// We use this as the "context" for our .NET delegate
struct Transformer {
int uppercase;
};
// Declare a typedef for our Transformer struct
typedef struct Transformer* Transformer_t;
// Creates an instance of a Transformer and configures it
Transformer_t transformer_create(
int uppercase // Pass 0 to lowercase or 1 to uppercase
) {
// Allocate memory for the transformer context
Transformer_t transformer = (Transformer_t)malloc(sizeof(Transformer_t));
// Configure it
transformer->uppercase = uppercase;
return transformer;
}
// Destroys an instance of a Transformer
void transformer_destroy(
void* context // The context (Transformer_t)
) {
if (!context) {
// Nothing to do
return;
}
// Cast the context to our Transformer_t
Transformer_t transformer = (Transformer_t)context;
printf("Destroying transformer\n");
// Free the memory we previously allocated in transformer_create
free(transformer);
}
// Does the actual transformation; Note that the signature must match the one of our .NET StringTransformerDelegate + a context as the first parameter
System_String_t transformer_transform(
void* context, // The context (Transformer_t)
System_String_t string // The string to transform
) {
if (!context ||
!string) {
// Nothing to do
return NULL;
}
// Cast the context to our Transformer_t
Transformer_t transformer = (Transformer_t)context;
// Should we upper- or lowercase?
int shouldUppercase = transformer->uppercase;
System_String_t transformedSystemString;
if (shouldUppercase) { // Uppercase
// Call the .NET System.String.ToUpper method
transformedSystemString = System_String_ToUpper(
string,
NULL // TODO: Error handling
);
} else { // Lowercase
// Call the .NET System.String.ToLower method
transformedSystemString = System_String_ToLower(
string,
NULL // TODO: Error handling
);
}
// Need to destroy all parameters passed to the delegate handler
System_String_Destroy(string);
// The return value will be destroyed by the .NET bindings so you don't need to worry about memory management of return values
return transformedSystemString;
}
// Entry point of the program
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Error: No input specified. Please provide a string to transform as the first and only argument.\n");
return 1;
}
// Get the original string from CLI parameters
const char* originalCString = argv[1];
// Convert the C String to a .NET System.String
System_String_t originalSystemString = DNStringFromC(originalCString);
// By setting this to 0 instead of 1 we'd get a lowercased string
int shouldUppercase = 1;
// Allocate memory for our Transformer_t and configure it
// The memory is freed later in the delegate destructor callback
Transformer_t transformer = transformer_create(shouldUppercase);
// Create a delegate object
Beyond_NET_Sample_Transformer_StringTransformerDelegate_t stringTransformerDelegate = Beyond_NET_Sample_Transformer_StringTransformerDelegate_Create(
transformer,
transformer_transform, // function pointer
transformer_destroy // destructor function pointer
);
// Pass the original string and the delegate object
System_String_t transformedSystemString = Beyond_NET_Sample_Transformer_TransformString(
originalSystemString,
stringTransformerDelegate,
NULL // TODO: Error handling
);
// Convert the returned .NET System.String to a C String
const char* transformedCString = DNStringToC(transformedSystemString);
// Print the original and the transformed strings
printf("Original: %s\nTransformed: %s\n", originalCString, transformedCString);
// Clean up
System_String_Destroy(originalSystemString);
System_String_Destroy(transformedSystemString);
free((void*)transformedCString);
// While we don't need the delegate object here anymore and thus can destroy it, .NET might still hold a reference to it
Beyond_NET_Sample_Transformer_StringTransformerDelegate_Destroy(stringTransformerDelegate);
// Force the GC to collect now which will cause our delegate destructor function (transformer_destroy) to be called
System_GC_Collect_1(NULL);
System_GC_WaitForPendingFinalizers(NULL);
return 0;
}