Skip to content

Instantly share code, notes, and snippets.

@Varriount
Last active February 18, 2017 19:33
Show Gist options
  • Save Varriount/42643edc4e817f767251bd4c75d58c22 to your computer and use it in GitHub Desktop.
Save Varriount/42643edc4e817f767251bd4c75d58c22 to your computer and use it in GitHub Desktop.
The below code is not valid C code - a preprocessor must be used:
```
CHAKRA_API
JsParseModuleSource(
_In_ JsModuleRecord requestModule,
_In_ JsSourceContext sourceContext,
_In_ BYTE* script,
_In_ unsigned int scriptLength,
_In_ JsParseModuleSourceFlags sourceFlag,
_Outptr_result_maybenull_ JsValueRef* exceptionValueRef);
```
`CHAKRA_API`, `_In_`, and `_Outptr_result_maybenull_` are all macros. They *might* be defined like below:
```
#define CHAKRA_API __declspec(dllexport) void
#define _In_
#define _Outptr_result_maybenull_
```
The problem with the above macros is that C2Nim normally tries turning such macros into Nim templates.
Nim templates are not equivalent to C macros however, and only a subset of C macros can be converted.
Additionally, even if a macro can be converted, it's not always used in a way that can be translated to Nim.
C2Nim would attempt such a translation, and fail.
```
template _In_(): expr =
discard
template _Outptr_result_maybenull_(): expr =
discard
template CHAKRA_API():
??? # C2Nim: "I don't know how to turn declspec into valid Nim code!"
```
Even if the translation of the macros succeeded, the macros usage couldn't be translated:
```
# Not valid Nim code!
proc JsParseModuleSource*(
_In_() JsModuleRecord requestModule,
_In_() JsSourceContext sourceContext,
_In_() ptr Byte script,
_In_() unsigned int scriptLength,
_In_() JsParseModuleSourceFlags sourceFlag,
_Outptr_result_maybenull_() ptr JsValueRef exceptionValueRef
): CHAKRA_API()
```
The solution to the above problems is a C2Nim-specific preprocessor macro, `#def`.
`#def` does what a `#define` in C does - performs exact replacement.
When translating a file, you replace `#define` with `#def` for any macros that are 'odd' (can't be translated).
Thus, the code
```
#def CHAKRA_API __declspec(dllexport) void
#def _In_
#def _Outptr_result_maybenull_
CHAKRA_API
JsParseModuleSource(
_In_ JsModuleRecord requestModule,
_In_ JsSourceContext sourceContext,
_In_ BYTE* script,
_In_ unsigned int scriptLength,
_In_ JsParseModuleSourceFlags sourceFlag,
_Outptr_result_maybenull_ JsValueRef* exceptionValueRef);
)
```
gets turned into the C code
```
__declspec(dllexport) void
JsParseModuleSource(
JsModuleRecord requestModule,
JsSourceContext sourceContext,
BYTE* script,
unsigned int scriptLength,
JsParseModuleSourceFlags sourceFlag,
JsValueRef* exceptionValueRef);
```
Unfortunately, we still have a problem! C2Nim doesn't know how to translate `__declspec(dllexport)`.
For this, we have to modify the source, and define `CHAKRA_API` as the blank macro `#def CHAKRA_API`.
```
#def CHAKRA_API void
#def _In_
#def _Outptr_result_maybenull_
CHAKRA_API
JsParseModuleSource(
_In_ JsModuleRecord requestModule,
_In_ JsSourceContext sourceContext,
_In_ BYTE* script,
_In_ unsigned int scriptLength,
_In_ JsParseModuleSourceFlags sourceFlag,
_Outptr_result_maybenull_ JsValueRef* exceptionValueRef);
```
Gets turned into the C code
```
JsParseModuleSource(
JsModuleRecord requestModule,
JsSourceContext sourceContext,
BYTE* script,
unsigned int scriptLength,
JsParseModuleSourceFlags sourceFlag,
JsValueRef* exceptionValueRef);
```
Which gets turned into the Nim code
```
proc JsParseModuleSource*(
JsModuleRecord requestModule,
JsSourceContext sourceContext,
ptr Byte script,
unsigned int scriptLength,
JsParseModuleSourceFlags sourceFlag,
ptr JsValueRef exceptionValueRef
): void
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment