From 4b8ea80e80c176dc22909890e051092f02777295 Mon Sep 17 00:00:00 2001
From: Ivan Folgueira Bande <ivansete@status.im>
Date: Sun, 11 Jun 2023 14:42:14 +0200
Subject: [PATCH 1/4] Adding example of nwaku integration in Go

---
 examples/golang/libwaku.h |  45 +++
 examples/golang/nimbase.h | 602 ++++++++++++++++++++++++++++++++++++++
 examples/golang/waku.go   |  89 ++++++
 3 files changed, 736 insertions(+)
 create mode 100644 examples/golang/libwaku.h
 create mode 100644 examples/golang/nimbase.h
 create mode 100644 examples/golang/waku.go

diff --git a/examples/golang/libwaku.h b/examples/golang/libwaku.h
new file mode 100644
index 0000000000..4621ecd320
--- /dev/null
+++ b/examples/golang/libwaku.h
@@ -0,0 +1,45 @@
+/* Generated by Nim Compiler v1.6.11 */
+#ifndef __libwaku__
+#define __libwaku__
+#define NIM_INTBITS 64
+
+#include "nimbase.h"
+#undef LANGUAGE_C
+#undef MIPSEB
+#undef MIPSEL
+#undef PPC
+#undef R3000
+#undef R4000
+#undef i386
+#undef linux
+#undef mips
+#undef near
+#undef far
+#undef powerpc
+#undef unix
+typedef struct ConfigNode ConfigNode;
+typedef struct NimStringDesc NimStringDesc;
+typedef struct TGenericSeq TGenericSeq;
+struct TGenericSeq {NI len;
+NI reserved;
+};
+struct NimStringDesc {  TGenericSeq Sup;NIM_CHAR data[SEQ_DECL_SIZE];
+};
+typedef N_CDECL_PTR(void, tyProc__5cp59bim9aJ4WupX5aVaD1Sg) (NCSTRING signal_0);
+N_LIB_PRIVATE N_NOCONV(void, signalHandler)(int sign);
+N_LIB_PRIVATE N_NIMCALL(NI, getRefcount)(void* p);
+N_LIB_IMPORT N_CDECL(NIM_BOOL, waku_new)(ConfigNode* config, NimStringDesc** jsonResp);
+N_LIB_IMPORT N_CDECL(NCSTRING, waku_version)(void);
+N_LIB_IMPORT N_CDECL(void, waku_set_event_callback)(tyProc__5cp59bim9aJ4WupX5aVaD1Sg callback);
+N_LIB_IMPORT N_CDECL(void, waku_content_topic)(NCSTRING appName, NU appVersion, NCSTRING contentTopicName, NCSTRING encoding, NimStringDesc** outContentTopic);
+N_LIB_IMPORT N_CDECL(void, waku_pubsub_topic)(NCSTRING topicName, NimStringDesc** outPubsubTopic);
+N_LIB_IMPORT N_CDECL(void, waku_default_pubsub_topic)(NimStringDesc** defPubsubTopic);
+N_LIB_IMPORT N_CDECL(NIM_BOOL, waku_relay_publish)(NCSTRING pubSubTopic, NCSTRING jsonWakuMessage, NI timeoutMs, NimStringDesc** jsonResp);
+N_LIB_IMPORT N_CDECL(void, waku_start)(void);
+N_LIB_IMPORT N_CDECL(void, waku_stop)(void);
+N_LIB_IMPORT N_CDECL(NIM_BOOL, waku_relay_subscribe)(NCSTRING pubSubTopic, NimStringDesc** jsonResp);
+N_LIB_IMPORT N_CDECL(NIM_BOOL, waku_relay_unsubscribe)(NCSTRING pubSubTopic, NimStringDesc** jsonResp);
+N_LIB_IMPORT N_CDECL(NIM_BOOL, waku_connect)(NCSTRING peerMultiAddr, NU timeoutMs, NimStringDesc** jsonResp);
+N_LIB_IMPORT N_CDECL(void, waku_poll)(void);
+N_LIB_IMPORT N_CDECL(void, NimMain)(void);
+#endif /* __libwaku__ */
diff --git a/examples/golang/nimbase.h b/examples/golang/nimbase.h
new file mode 100644
index 0000000000..a83bd30061
--- /dev/null
+++ b/examples/golang/nimbase.h
@@ -0,0 +1,602 @@
+/*
+
+            Nim's Runtime Library
+        (c) Copyright 2015 Andreas Rumpf
+
+    See the file "copying.txt", included in this
+    distribution, for details about the copyright.
+*/
+
+/* compiler symbols:
+__BORLANDC__
+_MSC_VER
+__WATCOMC__
+__LCC__
+__GNUC__
+__DMC__
+__POCC__
+__TINYC__
+__clang__
+__AVR__
+*/
+
+
+#ifndef NIMBASE_H
+#define NIMBASE_H
+
+/*------------ declaring a custom attribute to support using LLVM's Address Sanitizer ------------ */
+
+/*
+   This definition exists to provide support for using the LLVM ASAN (Address SANitizer) tooling with Nim. This
+   should only be used to mark implementations of the GC system that raise false flags with the ASAN tooling, or
+   for functions that are hot and need to be disabled for performance reasons. Based on the official ASAN
+   documentation, both the clang and gcc compilers are supported. In addition to that, a check is performed to
+   verify that the necessary attribute is supported by the compiler.
+
+   To flag a proc as ignored, append the following code pragma to the proc declaration:
+      {.codegenDecl: "CLANG_NO_SANITIZE_ADDRESS $# $#$#".}
+
+   For further information, please refer to the official documentation:
+     https://github.com/google/sanitizers/wiki/AddressSanitizer
+ */
+#define CLANG_NO_SANITIZE_ADDRESS
+#if defined(__clang__)
+#  if __has_attribute(no_sanitize_address)
+#    undef CLANG_NO_SANITIZE_ADDRESS
+#    define CLANG_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
+#  endif
+#endif
+
+
+/* ------------ ignore typical warnings in Nim-generated files ------------- */
+#if defined(__GNUC__) || defined(__clang__)
+#  pragma GCC diagnostic ignored "-Wpragmas"
+#  pragma GCC diagnostic ignored "-Wwritable-strings"
+#  pragma GCC diagnostic ignored "-Winvalid-noreturn"
+#  pragma GCC diagnostic ignored "-Wformat"
+#  pragma GCC diagnostic ignored "-Wlogical-not-parentheses"
+#  pragma GCC diagnostic ignored "-Wlogical-op-parentheses"
+#  pragma GCC diagnostic ignored "-Wshadow"
+#  pragma GCC diagnostic ignored "-Wunused-function"
+#  pragma GCC diagnostic ignored "-Wunused-variable"
+#  pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#  pragma GCC diagnostic ignored "-Wtautological-compare"
+#  pragma GCC diagnostic ignored "-Wswitch-bool"
+#  pragma GCC diagnostic ignored "-Wmacro-redefined"
+#  pragma GCC diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
+#  pragma GCC diagnostic ignored "-Wpointer-bool-conversion"
+#  pragma GCC diagnostic ignored "-Wconstant-conversion"
+#endif
+
+#if defined(_MSC_VER)
+#  pragma warning(disable: 4005 4100 4101 4189 4191 4200 4244 4293 4296 4309)
+#  pragma warning(disable: 4310 4365 4456 4477 4514 4574 4611 4668 4702 4706)
+#  pragma warning(disable: 4710 4711 4774 4800 4809 4820 4996 4090 4297)
+#endif
+/* ------------------------------------------------------------------------- */
+
+#if defined(__GNUC__) && !defined(__ZEPHYR__)
+/* Zephyr does some magic in it's headers that override the GCC stdlib. This breaks that. */
+#  define _GNU_SOURCE 1
+#endif
+
+#if defined(__TINYC__)
+/*#  define __GNUC__ 3
+#  define GCC_MAJOR 4
+#  define __GNUC_MINOR__ 4
+#  define __GNUC_PATCHLEVEL__ 5 */
+#  define __DECLSPEC_SUPPORTED 1
+#endif
+
+/* calling convention mess ----------------------------------------------- */
+#if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__) \
+                      || defined(__TINYC__)
+  /* these should support C99's inline */
+  /* the test for __POCC__ has to come before the test for _MSC_VER,
+     because PellesC defines _MSC_VER too. This is brain-dead. */
+#  define N_INLINE(rettype, name) inline rettype name
+#elif defined(__BORLANDC__) || defined(_MSC_VER)
+/* Borland's compiler is really STRANGE here; note that the __fastcall
+   keyword cannot be before the return type, but __inline cannot be after
+   the return type, so we do not handle this mess in the code generator
+   but rather here. */
+#  define N_INLINE(rettype, name) __inline rettype name
+#elif defined(__DMC__)
+#  define N_INLINE(rettype, name) inline rettype name
+#elif defined(__WATCOMC__)
+#  define N_INLINE(rettype, name) __inline rettype name
+#else /* others are less picky: */
+#  define N_INLINE(rettype, name) rettype __inline name
+#endif
+
+#define N_INLINE_PTR(rettype, name) rettype (*name)
+
+#if defined(__POCC__)
+#  define NIM_CONST /* PCC is really picky with const modifiers */
+#  undef _MSC_VER /* Yeah, right PCC defines _MSC_VER even if it is
+                     not that compatible. Well done. */
+#elif defined(__cplusplus)
+#  define NIM_CONST /* C++ is picky with const modifiers */
+#else
+#  define NIM_CONST  const
+#endif
+
+/*
+  NIM_THREADVAR declaration based on
+  http://stackoverflow.com/questions/18298280/how-to-declare-a-variable-as-thread-local-portably
+*/
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
+#  define NIM_THREADVAR _Thread_local
+#elif defined _WIN32 && ( \
+       defined _MSC_VER || \
+       defined __ICL || \
+       defined __DMC__ || \
+       defined __BORLANDC__ )
+#  define NIM_THREADVAR __declspec(thread)
+#elif defined(__TINYC__) || defined(__GENODE__)
+#  define NIM_THREADVAR
+/* note that ICC (linux) and Clang are covered by __GNUC__ */
+#elif defined __GNUC__ || \
+       defined __SUNPRO_C || \
+       defined __xlC__
+#  define NIM_THREADVAR __thread
+#else
+#  error "Cannot define NIM_THREADVAR"
+#endif
+
+#if defined(__cplusplus)
+  #define NIM_THREAD_LOCAL thread_local
+#endif
+
+/* --------------- how int64 constants should be declared: ----------- */
+#if defined(__GNUC__) || defined(__LCC__) || \
+    defined(__POCC__) || defined(__DMC__) || defined(_MSC_VER)
+#  define IL64(x) x##LL
+#else /* works only without LL */
+#  define IL64(x) ((NI64)x)
+#endif
+
+/* ---------------- casting without correct aliasing rules ----------- */
+
+#if defined(__GNUC__)
+#  define NIM_CAST(type, ptr) (((union{type __x__;}*)(ptr))->__x__)
+#else
+#  define NIM_CAST(type, ptr) ((type)(ptr))
+#endif
+
+
+/* ------------------------------------------------------------------- */
+#ifdef  __cplusplus
+#  define NIM_EXTERNC extern "C"
+#else
+#  define NIM_EXTERNC
+#endif
+
+#if defined(WIN32) || defined(_WIN32) /* only Windows has this mess... */
+#  define N_LIB_PRIVATE
+#  define N_CDECL(rettype, name) rettype __cdecl name
+#  define N_STDCALL(rettype, name) rettype __stdcall name
+#  define N_SYSCALL(rettype, name) rettype __syscall name
+#  define N_FASTCALL(rettype, name) rettype __fastcall name
+#  define N_THISCALL(rettype, name) rettype __thiscall name
+#  define N_SAFECALL(rettype, name) rettype __stdcall name
+/* function pointers with calling convention: */
+#  define N_CDECL_PTR(rettype, name) rettype (__cdecl *name)
+#  define N_STDCALL_PTR(rettype, name) rettype (__stdcall *name)
+#  define N_SYSCALL_PTR(rettype, name) rettype (__syscall *name)
+#  define N_FASTCALL_PTR(rettype, name) rettype (__fastcall *name)
+#  define N_THISCALL_PTR(rettype, name) rettype (__thiscall *name)
+#  define N_SAFECALL_PTR(rettype, name) rettype (__stdcall *name)
+
+#  ifdef __cplusplus
+#    define N_LIB_EXPORT  NIM_EXTERNC __declspec(dllexport)
+#  else
+#    define N_LIB_EXPORT  NIM_EXTERNC __declspec(dllexport)
+#  endif
+#  define N_LIB_EXPORT_VAR  __declspec(dllexport)
+#  define N_LIB_IMPORT  extern __declspec(dllimport)
+#else
+#  define N_LIB_PRIVATE __attribute__((visibility("hidden")))
+#  if defined(__GNUC__)
+#    define N_CDECL(rettype, name) rettype name
+#    define N_STDCALL(rettype, name) rettype name
+#    define N_SYSCALL(rettype, name) rettype name
+#    define N_FASTCALL(rettype, name) __attribute__((fastcall)) rettype name
+#    define N_SAFECALL(rettype, name) rettype name
+/*   function pointers with calling convention: */
+#    define N_CDECL_PTR(rettype, name) rettype (*name)
+#    define N_STDCALL_PTR(rettype, name) rettype (*name)
+#    define N_SYSCALL_PTR(rettype, name) rettype (*name)
+#    define N_FASTCALL_PTR(rettype, name) __attribute__((fastcall)) rettype (*name)
+#    define N_SAFECALL_PTR(rettype, name) rettype (*name)
+#  else
+#    define N_CDECL(rettype, name) rettype name
+#    define N_STDCALL(rettype, name) rettype name
+#    define N_SYSCALL(rettype, name) rettype name
+#    define N_FASTCALL(rettype, name) rettype name
+#    define N_SAFECALL(rettype, name) rettype name
+/*   function pointers with calling convention: */
+#    define N_CDECL_PTR(rettype, name) rettype (*name)
+#    define N_STDCALL_PTR(rettype, name) rettype (*name)
+#    define N_SYSCALL_PTR(rettype, name) rettype (*name)
+#    define N_FASTCALL_PTR(rettype, name) rettype (*name)
+#    define N_SAFECALL_PTR(rettype, name) rettype (*name)
+#  endif
+#  define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default")))
+#  define N_LIB_EXPORT_VAR  __attribute__((visibility("default")))
+#  define N_LIB_IMPORT  extern
+#endif
+
+#define N_NOCONV(rettype, name) rettype name
+/* specify no calling convention */
+#define N_NOCONV_PTR(rettype, name) rettype (*name)
+
+#if defined(__GNUC__) || defined(__ICC__)
+#  define N_NOINLINE(rettype, name) rettype __attribute__((__noinline__)) name
+#elif defined(_MSC_VER)
+#  define N_NOINLINE(rettype, name) __declspec(noinline) rettype name
+#else
+#  define N_NOINLINE(rettype, name) rettype name
+#endif
+
+#define N_NOINLINE_PTR(rettype, name) rettype (*name)
+
+#if defined(__BORLANDC__) || defined(__WATCOMC__) || \
+    defined(__POCC__) || defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
+/* these compilers have a fastcall so use it: */
+#  ifdef __TINYC__
+#    define N_NIMCALL(rettype, name) rettype __attribute((__fastcall)) name
+#    define N_NIMCALL_PTR(rettype, name) rettype (__attribute((__fastcall)) *name)
+#    define N_RAW_NIMCALL __attribute((__fastcall))
+#  else
+#    define N_NIMCALL(rettype, name) rettype __fastcall name
+#    define N_NIMCALL_PTR(rettype, name) rettype (__fastcall *name)
+#    define N_RAW_NIMCALL __fastcall
+#  endif
+#else
+#  define N_NIMCALL(rettype, name) rettype name /* no modifier */
+#  define N_NIMCALL_PTR(rettype, name) rettype (*name)
+#  define N_RAW_NIMCALL
+#endif
+
+#define N_CLOSURE(rettype, name) N_NIMCALL(rettype, name)
+#define N_CLOSURE_PTR(rettype, name) N_NIMCALL_PTR(rettype, name)
+
+/* ----------------------------------------------------------------------- */
+
+#define COMMA ,
+
+#include <limits.h>
+#include <stddef.h>
+
+// define NIM_STATIC_ASSERT
+// example use case: CT sizeof for importc types verification
+// where we have {.completeStruct.} (or lack of {.incompleteStruct.})
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
+#define NIM_STATIC_ASSERT(x, msg) _Static_assert((x), msg)
+#elif defined(__cplusplus)
+#define NIM_STATIC_ASSERT(x, msg) static_assert((x), msg)
+#else
+#define NIM_STATIC_ASSERT(x, msg) typedef int NIM_STATIC_ASSERT_AUX[(x) ? 1 : -1];
+// On failure, your C compiler will say something like:
+//   "error: 'NIM_STATIC_ASSERT_AUX' declared as an array with a negative size"
+// we could use a better fallback to also show line number, using:
+// http://www.pixelbeat.org/programming/gcc/static_assert.html
+#endif
+
+/* C99 compiler? */
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901))
+#  define HAVE_STDINT_H
+#endif
+
+/* Known compiler with stdint.h that doesn't fit the general pattern? */
+#if defined(__LCC__) || defined(__DMC__) || defined(__POCC__) || \
+  defined(__AVR__) || (defined(__cplusplus) && (__cplusplus < 201103))
+#  define HAVE_STDINT_H
+#endif
+
+#if (!defined(HAVE_STDINT_H) && defined(__cplusplus) && (__cplusplus >= 201103))
+#  define HAVE_CSTDINT
+#endif
+
+
+/* wrap all Nim typedefs into namespace Nim */
+#ifdef USE_NIM_NAMESPACE
+#ifdef HAVE_CSTDINT
+#include <cstdint>
+#else
+#include <stdint.h>
+#endif
+namespace USE_NIM_NAMESPACE {
+#endif
+
+// preexisting check, seems paranoid, maybe remove
+#if defined(NIM_TRUE) || defined(NIM_FALSE) || defined(NIM_BOOL)
+#error "nim reserved preprocessor macros clash"
+#endif
+
+/* bool types (C++ has it): */
+#ifdef __cplusplus
+#define NIM_BOOL bool
+#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901)
+// see #13798: to avoid conflicts for code emitting `#include <stdbool.h>`
+#define NIM_BOOL _Bool
+#else
+typedef unsigned char NIM_BOOL; // best effort
+#endif
+
+NIM_STATIC_ASSERT(sizeof(NIM_BOOL) == 1, ""); // check whether really needed
+NIM_STATIC_ASSERT(CHAR_BIT == 8, "");
+  // fail fast for (rare) environments where this doesn't hold, as some implicit
+  // assumptions would need revisiting (e.g. `uint8` or https://github.com/nim-lang/Nim/pull/18505)
+
+#define NIM_TRUE true
+#define NIM_FALSE false
+
+#ifdef __cplusplus
+#  if __cplusplus >= 201103L
+#    /* nullptr is more type safe (less implicit conversions than 0) */
+#    define NIM_NIL nullptr
+#  else
+#    // both `((void*)0)` and `NULL` would cause codegen to emit
+#    // error: assigning to 'Foo *' from incompatible type 'void *'
+#    // but codegen could be fixed if need. See also potential caveat regarding
+#    // NULL.
+#    // However, `0` causes other issues, see #13798
+#    define NIM_NIL 0
+#  endif
+#else
+#  include <stdbool.h>
+#  define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so
+                              the generated code does not rely on it anymore */
+#endif
+
+#if defined(__BORLANDC__) || defined(__DMC__) \
+   || defined(__WATCOMC__) || defined(_MSC_VER)
+typedef signed char NI8;
+typedef signed short int NI16;
+typedef signed int NI32;
+typedef __int64 NI64;
+/* XXX: Float128? */
+typedef unsigned char NU8;
+typedef unsigned short int NU16;
+typedef unsigned int NU32;
+typedef unsigned __int64 NU64;
+#elif defined(HAVE_STDINT_H)
+#ifndef USE_NIM_NAMESPACE
+#  include <stdint.h>
+#endif
+typedef int8_t NI8;
+typedef int16_t NI16;
+typedef int32_t NI32;
+typedef int64_t NI64;
+typedef uint8_t NU8;
+typedef uint16_t NU16;
+typedef uint32_t NU32;
+typedef uint64_t NU64;
+#elif defined(HAVE_CSTDINT)
+#ifndef USE_NIM_NAMESPACE
+#  include <cstdint>
+#endif
+typedef std::int8_t NI8;
+typedef std::int16_t NI16;
+typedef std::int32_t NI32;
+typedef std::int64_t NI64;
+typedef std::uint8_t NU8;
+typedef std::uint16_t NU16;
+typedef std::uint32_t NU32;
+typedef std::uint64_t NU64;
+#else
+/* Unknown compiler/version, do our best */
+#ifdef __INT8_TYPE__
+typedef __INT8_TYPE__ NI8;
+#else
+typedef signed char NI8;
+#endif
+#ifdef __INT16_TYPE__
+typedef __INT16_TYPE__ NI16;
+#else
+typedef signed short int NI16;
+#endif
+#ifdef __INT32_TYPE__
+typedef __INT32_TYPE__ NI32;
+#else
+typedef signed int NI32;
+#endif
+#ifdef __INT64_TYPE__
+typedef __INT64_TYPE__ NI64;
+#else
+typedef long long int NI64;
+#endif
+/* XXX: Float128? */
+#ifdef __UINT8_TYPE__
+typedef __UINT8_TYPE__ NU8;
+#else
+typedef unsigned char NU8;
+#endif
+#ifdef __UINT16_TYPE__
+typedef __UINT16_TYPE__ NU16;
+#else
+typedef unsigned short int NU16;
+#endif
+#ifdef __UINT32_TYPE__
+typedef __UINT32_TYPE__ NU32;
+#else
+typedef unsigned int NU32;
+#endif
+#ifdef __UINT64_TYPE__
+typedef __UINT64_TYPE__ NU64;
+#else
+typedef unsigned long long int NU64;
+#endif
+#endif
+
+#ifdef NIM_INTBITS
+#  if NIM_INTBITS == 64
+typedef NI64 NI;
+typedef NU64 NU;
+#  elif NIM_INTBITS == 32
+typedef NI32 NI;
+typedef NU32 NU;
+#  elif NIM_INTBITS == 16
+typedef NI16 NI;
+typedef NU16 NU;
+#  elif NIM_INTBITS == 8
+typedef NI8 NI;
+typedef NU8 NU;
+#  else
+#    error "invalid bit width for int"
+#  endif
+#endif
+
+// for now there isn't an easy way for C code to reach the program result
+// when hot code reloading is ON - users will have to:
+// load the nimhcr.dll, get the hcrGetGlobal proc from there and use it
+#ifndef NIM_HOT_CODE_RELOADING
+extern NI nim_program_result;
+#endif
+
+typedef float NF32;
+typedef double NF64;
+typedef double NF;
+
+typedef char NIM_CHAR;
+typedef char* NCSTRING;
+
+#ifdef NIM_BIG_ENDIAN
+#  define NIM_IMAN 1
+#else
+#  define NIM_IMAN 0
+#endif
+
+#define NIM_STRLIT_FLAG ((NU)(1) << ((NIM_INTBITS) - 2)) /* This has to be the same as system.strlitFlag! */
+
+#define STRING_LITERAL(name, str, length) \
+   static const struct {                   \
+     TGenericSeq Sup;                      \
+     NIM_CHAR data[(length) + 1];          \
+  } name = {{length, (NI) ((NU)length | NIM_STRLIT_FLAG)}, str}
+
+/* declared size of a sequence/variable length array: */
+#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
+#  define SEQ_DECL_SIZE /* empty is correct! */
+#else
+#  define SEQ_DECL_SIZE 1000000
+#endif
+
+#define ALLOC_0(size)  calloc(1, size)
+#define DL_ALLOC_0(size) dlcalloc(1, size)
+
+#define paramCount() cmdCount
+
+// NAN definition copied from math.h included in the Windows SDK version 10.0.14393.0
+#ifndef NAN
+#  ifndef _HUGE_ENUF
+#    define _HUGE_ENUF  1e+300  // _HUGE_ENUF*_HUGE_ENUF must overflow
+#  endif
+#  define NAN_INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
+#  define NAN ((float)(NAN_INFINITY * 0.0F))
+#endif
+
+#ifndef INF
+#  ifdef INFINITY
+#    define INF INFINITY
+#  elif defined(HUGE_VAL)
+#    define INF  HUGE_VAL
+#  elif defined(_MSC_VER)
+#    include <float.h>
+#    define INF (DBL_MAX+DBL_MAX)
+#  else
+#    define INF (1.0 / 0.0)
+#  endif
+#endif
+
+typedef struct TFrame_ TFrame;
+struct TFrame_ {
+  TFrame* prev;
+  NCSTRING procname;
+  NI line;
+  NCSTRING filename;
+  NI16 len;
+  NI16 calldepth;
+  NI frameMsgLen;
+};
+
+#define NIM_POSIX_INIT  __attribute__((constructor))
+
+#ifdef __GNUC__
+#  define NIM_LIKELY(x) __builtin_expect(x, 1)
+#  define NIM_UNLIKELY(x) __builtin_expect(x, 0)
+/* We need the following for the posix wrapper. In particular it will give us
+   POSIX_SPAWN_USEVFORK: */
+#  ifndef _GNU_SOURCE
+#    define _GNU_SOURCE
+#  endif
+#else
+#  define NIM_LIKELY(x) (x)
+#  define NIM_UNLIKELY(x) (x)
+#endif
+
+#if 0 // defined(__GNUC__) || defined(__clang__)
+// not needed anymore because the stack marking cares about
+// interior pointers now
+static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
+#  define GC_GUARD __attribute__ ((cleanup(GCGuard)))
+#else
+#  define GC_GUARD
+#endif
+
+// Test to see if Nim and the C compiler agree on the size of a pointer.
+NIM_STATIC_ASSERT(sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8, "");
+
+#ifdef USE_NIM_NAMESPACE
+}
+#endif
+
+#if defined(_MSC_VER)
+#  define NIM_ALIGN(x)  __declspec(align(x))
+#  define NIM_ALIGNOF(x) __alignof(x)
+#else
+#  define NIM_ALIGN(x)  __attribute__((aligned(x)))
+#  define NIM_ALIGNOF(x) __alignof__(x)
+#endif
+
+/* ---------------- platform specific includes ----------------------- */
+
+/* VxWorks related includes */
+#if defined(__VXWORKS__)
+#  include <sys/types.h>
+#  include <types/vxWind.h>
+#  include <tool/gnu/toolMacros.h>
+#elif defined(__FreeBSD__)
+#  include <sys/types.h>
+#endif
+
+/* these exist to make the codegen logic simpler */
+#define nimModInt(a, b, res) (((*res) = (a) % (b)), 0)
+#define nimModInt64(a, b, res) (((*res) = (a) % (b)), 0)
+
+#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(NIM_EmulateOverflowChecks)
+  /* these exist because we cannot have .compilerProcs that are importc'ed
+    by a different name */
+
+  #define nimAddInt64(a, b, res) __builtin_saddll_overflow(a, b, (long long int*)res)
+  #define nimSubInt64(a, b, res) __builtin_ssubll_overflow(a, b, (long long int*)res)
+  #define nimMulInt64(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res)
+
+  #if NIM_INTBITS == 32
+    #define nimAddInt(a, b, res) __builtin_sadd_overflow(a, b, res)
+    #define nimSubInt(a, b, res) __builtin_ssub_overflow(a, b, res)
+    #define nimMulInt(a, b, res) __builtin_smul_overflow(a, b, res)
+  #else
+    /* map it to the 'long long' variant */
+    #define nimAddInt(a, b, res) __builtin_saddll_overflow(a, b, (long long int*)res)
+    #define nimSubInt(a, b, res) __builtin_ssubll_overflow(a, b, (long long int*)res)
+    #define nimMulInt(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res)
+  #endif
+#endif
+
+#define NIM_NOALIAS __restrict
+/* __restrict is said to work for all the C(++) compilers out there that we support */
+
+#endif /* NIMBASE_H */
diff --git a/examples/golang/waku.go b/examples/golang/waku.go
new file mode 100644
index 0000000000..2daba3b8bd
--- /dev/null
+++ b/examples/golang/waku.go
@@ -0,0 +1,89 @@
+package main
+
+/*
+	#cgo LDFLAGS: -L./ -lwaku -Wl,--allow-multiple-definition
+
+	#include "libwaku.h"
+
+	static NimStringDesc wakuString;
+	NimStringDesc* mResp = &wakuString;
+
+	char* data(NimStringDesc* a) {
+		return a->data;
+	}
+
+	extern void eventHandler(char* msg);
+
+	void cGoEventHandler(char* msg) {
+		eventHandler(msg);
+	}
+
+	void setCallback() {
+		waku_set_event_callback(cGoEventHandler);
+	}
+
+	struct ConfigNode {
+		NCSTRING host;
+		NU       port;
+		NCSTRING key;
+		NIM_BOOL relay;
+		NCSTRING peers;
+	};
+*/
+import "C"
+
+import (
+	"os"
+	"fmt"
+	"runtime"
+)
+
+//export eventHandler
+func eventHandler(msg *C.char) {
+	fmt.Println("Event received: ", C.GoString(msg))
+}
+
+func main() {
+	runtime.LockOSThread()
+
+	C.NimMain()
+
+	cfgNode := C.ConfigNode{}
+
+	cfgNode.host = C.CString("0.0.0.0")
+	cfgNode.port = 60000
+	cfgNode.key  = C.CString("364d111d729a6eb6d2e6113e163f017b5ef03a6f94c9b5b7bb1bb36fa5cb07a9")
+	cfgNode.relay = true
+	cfgNode.peers = nil
+
+	fmt.Println("Git Version: ", C.GoString( C.waku_version() ))
+	C.waku_default_pubsub_topic(&C.mResp);
+	defaultPubsubTopic := C.data( C.mResp )
+
+	fmt.Println("Default pubsub topic: ", C.GoString( defaultPubsubTopic ) )
+	fmt.Println("Bind addr: ", C.GoString(cfgNode.host), ":", cfgNode.port)
+
+	if cfgNode.relay {
+		fmt.Println("Waku Relay enabled")
+	} else {
+		fmt.Println("Waku Relay disabled")
+	}
+
+	if ! C.waku_new(&cfgNode, &C.mResp) {
+		fmt.Println("Error creating WakuNode: ", C.GoString(C.data(C.mResp)));
+		os.Exit(-1)
+	}
+
+	C.setCallback()
+	C.waku_start()
+
+	if ! C.waku_relay_subscribe(defaultPubsubTopic, &C.mResp) {
+		fmt.Println("Error subscribing to PubsubTopic: ",
+					C.GoString(C.data(C.mResp)));
+		os.Exit(-1)
+	}
+
+	for {
+		C.waku_poll()
+	}
+}

From f7e7b0b4d5a5138eb2a7067bbe6ff1ae9cec8cbf Mon Sep 17 00:00:00 2001
From: Ivan Folgueira Bande <ivansete@status.im>
Date: Mon, 12 Jun 2023 15:47:32 +0200
Subject: [PATCH 2/4] libwaku.nim: adapting code to latest changes made in
 34a926319

---
 library/libwaku.nim | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/library/libwaku.nim b/library/libwaku.nim
index 995d7f7a37..a608de0dd7 100644
--- a/library/libwaku.nim
+++ b/library/libwaku.nim
@@ -47,16 +47,12 @@ type
 
 var eventCallback:EventCallback = nil
 
-proc relayEventCallback(pubsubTopic: string, data: seq[byte]): Future[void] {.gcsafe, raises: [Defect].} =
+proc relayEventCallback(pubsubTopic: string,
+                        msg: WakuMessage):
+                        Future[void] {.gcsafe, raises: [Defect].} =
   # Callback that hadles the Waku Relay events. i.e. messages or errors.
   if not isNil(eventCallback):
-    let msg = WakuMessage.decode(data)
-    var event: JsonSignal
-    if msg.isOk():
-      event = JsonMessageEvent.new(pubsubTopic, msg.value)
-    else:
-      let errorMsg = string("Error decoding message.") & $msg.error
-      event = JsonErrorEvent.new(errorMsg)
+    let event = JsonMessageEvent.new(pubsubTopic, msg)
 
     try:
       eventCallback(cstring($event))
@@ -303,7 +299,8 @@ Kindly set it with the 'waku_set_event_callback' function""")
     jsonResp = errResp("Cannot subscribe without Waku Relay enabled.")
     return false
 
-  node.wakuRelay.subscribe(PubsubTopic($pubSubTopic), PubsubRawHandler(relayEventCallback))
+  node.wakuRelay.subscribe(PubsubTopic($pubSubTopic),
+                           WakuRelayHandler(relayEventCallback))
 
   jsonResp = okResp("true")
   return true
@@ -323,7 +320,7 @@ Kindly set it with the 'waku_set_event_callback' function""")
     jsonResp = errResp("Cannot unsubscribe without Waku Relay enabled.")
     return false
 
-  node.wakuRelay.unsubscribeAll(PubsubTopic($pubSubTopic))
+  node.wakuRelay.unsubscribe(PubsubTopic($pubSubTopic))
 
   jsonResp = okResp("true")
   return true

From 256ffeb5315de6b786a6b963daeed0efa064f6d9 Mon Sep 17 00:00:00 2001
From: Ivan Folgueira Bande <ivansete@status.im>
Date: Mon, 12 Jun 2023 18:42:40 +0200
Subject: [PATCH 3/4] Makefile: copying libwaku.so to 'examples/golang' when it
 is built

---
 Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile b/Makefile
index 131718d245..806b0e2697 100644
--- a/Makefile
+++ b/Makefile
@@ -298,6 +298,7 @@ else
 		echo -e $(BUILD_MSG) "build/$@.so" && \
 		$(ENV_SCRIPT) nim libwakuDynamic $(NIM_PARAMS) $(EXPERIMENTAL_PARAMS) waku.nims
 endif
+		cp build/libwaku.so examples/golang/
 
 cwaku_example: | build libwaku
 	echo -e $(BUILD_MSG) "build/$@" && \

From 7d1a8715f4f28374d88f59f1653a32d265b06f09 Mon Sep 17 00:00:00 2001
From: Ivan Folgueira Bande <ivansete@status.im>
Date: Mon, 12 Jun 2023 18:51:13 +0200
Subject: [PATCH 4/4] Adding waku.go and README.md to give better insight on
 how to handle the go example.

---
 examples/golang/README.md | 59 +++++++++++++++++++++++++++++++++++++++
 examples/golang/waku.go   | 31 ++++++++++++++++----
 2 files changed, 84 insertions(+), 6 deletions(-)
 create mode 100644 examples/golang/README.md

diff --git a/examples/golang/README.md b/examples/golang/README.md
new file mode 100644
index 0000000000..d143659ce4
--- /dev/null
+++ b/examples/golang/README.md
@@ -0,0 +1,59 @@
+
+## Summary
+
+This is a simple example on how to integrate the `libwaku.so` library in a
+Golang app.
+
+[cgo](https://pkg.go.dev/cmd/cgo) is used in this example.
+
+There are comments in the file `waku.go` that are considered by the cgo itself and
+shouldn't be arbitrarily changed unless required.
+
+The important comments in the `waku.go` are the ones above the `import "C"` statement and
+above the `eventHandler` function.
+
+## libwaku.so
+
+Before running the example, make sure to properly export the LD_LIBRARY_PATH
+with the path that contains the target `libwaku.so` library.
+
+e.g.
+From the repo's root folder:
+```code
+export LD_LIBRARY_PATH=build
+```
+
+In order to build the `libwaku.so`, go to the repo's root folder and
+invoke the next command, which will create `libwaku.so` under the `build` folder:
+
+```code
+make libwaku
+```
+This will both generate the `libwaku.so` file under the `build` and
+the `examples/golang/` fodler.
+It is important to notice that there should be a `libwaku.so` at the same level as the `waku.go` file as per how `waku.go` is implemented.
+
+## libwaku.h & nimbase.h
+
+This is the header associated with the `libwaku.so`.
+
+The `libwaku.h` is auto-generated when building the `libwaku.so`.
+
+Everytime a new `libwaku.so` is built, the `libwaku.h` file gets stored in
+<REPO_ROOT_DIR>/nimcache/release/libwaku/libwaku.h.
+
+However, the `libwaku.h` is kept version-controlled just for commodity.
+It might be needed to update the `libwaku.h` header if a new function
+is added to the `libwaku.so` or any signature is modified.
+
+## Running the example
+
+- Open a terminal
+- cd <...>/nwaku/
+- ```code
+  export LD_LIBRARY_PATH=build
+  ```
+- ```code
+  go run examples/golang/waku.go
+  ```
+  note: `--help` can be appended to the end of the previous command to get better insight of possible params
diff --git a/examples/golang/waku.go b/examples/golang/waku.go
index 2daba3b8bd..f6f118f075 100644
--- a/examples/golang/waku.go
+++ b/examples/golang/waku.go
@@ -36,6 +36,7 @@ import (
 	"os"
 	"fmt"
 	"runtime"
+	"flag"
 )
 
 //export eventHandler
@@ -46,15 +47,33 @@ func eventHandler(msg *C.char) {
 func main() {
 	runtime.LockOSThread()
 
+	// Setup the nim runtime and GC.
 	C.NimMain()
 
-	cfgNode := C.ConfigNode{}
+	var host string
+	var port int
+	var key string
+	var relay int
+
+	flag.StringVar(&host, "host", "0.0.0.0", "Node's host.")
+	flag.IntVar(&port, "port", 60000, "Node's port.")
+	flag.StringVar(&key, "key", "",
+	`P2P node private key as 64 char hex string.
+e.g.: 364d111d729a6eb6d2e6113e163f017b5ef03a6f94c9b5b7bb1bb36fa5cb07a9`)
+	flag.IntVar(&relay, "relay", 1, "1 -> Enable Relay protocol. 0 -> disable.")
+	flag.Parse()
+
+	if key == "" {
+		fmt.Println("Please set a valid P2P private node key.")
+		fmt.Println("Run with --help to get a better insight.")
+		os.Exit(1)
+	}
 
-	cfgNode.host = C.CString("0.0.0.0")
-	cfgNode.port = 60000
-	cfgNode.key  = C.CString("364d111d729a6eb6d2e6113e163f017b5ef03a6f94c9b5b7bb1bb36fa5cb07a9")
-	cfgNode.relay = true
-	cfgNode.peers = nil
+	cfgNode := C.ConfigNode{}
+	cfgNode.host = C.CString(host)
+	cfgNode.port = C.ulong(port)
+	cfgNode.key = C.CString(key)
+	cfgNode.relay = relay == 1
 
 	fmt.Println("Git Version: ", C.GoString( C.waku_version() ))
 	C.waku_default_pubsub_topic(&C.mResp);