diff --git a/.gitignore b/.gitignore index d2c6493..3d4429d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ RangerMetrics.h RangerMetrics_x64.h + +*.log + +settings.json diff --git a/.vs/Arma3-Influx/config/applicationhost.config b/.vs/Arma3-Influx/config/applicationhost.config new file mode 100644 index 0000000..98fc570 --- /dev/null +++ b/.vs/Arma3-Influx/config/applicationhost.config @@ -0,0 +1,1015 @@ + + + + + + + +
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.vs/Arma3-Influx/v16/.suo b/.vs/Arma3-Influx/v16/.suo new file mode 100644 index 0000000..67039ed Binary files /dev/null and b/.vs/Arma3-Influx/v16/.suo differ diff --git a/.vs/Arma3-Influx/v16/Browse.VC.db b/.vs/Arma3-Influx/v16/Browse.VC.db new file mode 100644 index 0000000..1df4f2e Binary files /dev/null and b/.vs/Arma3-Influx/v16/Browse.VC.db differ diff --git a/.vs/Arma3-Influx/v16/ipch/AutoPCH/e4ccdcd327ffb12b/RVEXTENSION.ipch b/.vs/Arma3-Influx/v16/ipch/AutoPCH/e4ccdcd327ffb12b/RVEXTENSION.ipch new file mode 100644 index 0000000..4e4b8cb Binary files /dev/null and b/.vs/Arma3-Influx/v16/ipch/AutoPCH/e4ccdcd327ffb12b/RVEXTENSION.ipch differ diff --git a/.vs/Arma3-Influx/v16/ipch/AutoPCH/f1453785bde63265/RVEXTENSION.ipch b/.vs/Arma3-Influx/v16/ipch/AutoPCH/f1453785bde63265/RVEXTENSION.ipch new file mode 100644 index 0000000..b91674e Binary files /dev/null and b/.vs/Arma3-Influx/v16/ipch/AutoPCH/f1453785bde63265/RVEXTENSION.ipch differ diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000..22a4bcd --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": "x64-Release" +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..6bbca40 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,7 @@ +{ + "ExpandedNodes": [ + "" + ], + "SelectedNode": "\\RVExtension.c", + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000..860e823 Binary files /dev/null and b/.vs/slnx.sqlite differ diff --git a/.vs/tasks.vs.json b/.vs/tasks.vs.json new file mode 100644 index 0000000..34e4b37 --- /dev/null +++ b/.vs/tasks.vs.json @@ -0,0 +1,10 @@ +{ + "version": "0.2.1", + "tasks": [ + { + "taskLabel": "task-Arma3-Influx", + "appliesTo": "/", + "type": "launch" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 22ae3d6..5165bcf 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,24 @@ A3 extension for sending metrics to InfluxDB using Golang -> See more: https://github.com/code34/armago_x64 +## Build + +### Windows + +_Requires Go 1.20.1+ & MinGW_ + + ```powershell + $ENV:GOARCH = "amd64" + $ENV:CGO_ENABLED = 1 + go build -o RangerMetrics_x64.dll -buildmode=c-shared . + ``` + +To validate exported functions: + + ```powershell + . "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\dumpbin.exe" /exports .\RangerMetrics_x64.dll + ``` + +## Notes +> +> See more: diff --git a/RVExtension.c b/RVExtension.c index 76f35fc..9ef7b67 100644 --- a/RVExtension.c +++ b/RVExtension.c @@ -2,38 +2,64 @@ #include "extensionCallback.h" -extern void goRVExtension(char *output, int outputSize, char *input); -extern void goRVExtensionVersion(char *output, int outputSize); -extern int goRVExtensionArgs(char* output, int outputSize, char* input, char** argv, int argc); -// extern void goRVExtensionRegisterCallback(extensionCallback fnc); +extern void goRVExtension(char *output, size_t outputSize, char *input); +extern void goRVExtensionVersion(char *output, size_t outputSize); +extern void goRVExtensionArgs(char *output, size_t outputSize, char *input, char **argv, int argc); +extern void goRVExtensionRegisterCallback(extensionCallback fnc); +// context is new +extern void goRVExtensionContext(const char **argv, int argc); -//--- Called by Engine on extension load -__attribute__((dllexport)) void RVExtensionVersion(char *output, int outputSize); -//--- STRING callExtension STRING -__attribute__((dllexport)) void RVExtension(char *output, int outputSize, char *input); -//--- STRING callExtension ARRAY -__attribute__((dllexport)) int RVExtensionArgs(char *output, int outputSize, char* input, char** argv, int argc); - - - -void RVExtension(char *output, int outputSize, char *input) +#ifdef WIN64 +__declspec(dllexport) void RVExtension(char *output, size_t outputSize, char *input) { - goRVExtension(output, outputSize, input); + goRVExtension(output, outputSize, input); } -void RVExtensionVersion(char *output, int outputSize) +__declspec(dllexport) void RVExtensionVersion(char *output, size_t outputSize) { - goRVExtensionVersion(output, outputSize); + goRVExtensionVersion(output, outputSize); } - -int RVExtensionArgs(char *output, int outputSize, char* input, char** argv, int argc) +__declspec(dllexport) void RVExtensionArgs(char *output, size_t outputSize, char *input, char **argv, int argc) { - return goRVExtensionArgs(output, outputSize, input, argv, argc); + goRVExtensionArgs(output, outputSize, input, argv, argc); } +__declspec(dllexport) void RVExtensionRegisterCallback(extensionCallback fnc) +{ + goRVExtensionRegisterCallback(fnc); +} -// __declspec(dllexport) void RVExtensionRegisterCallback(extensionCallback fnc) { -// goRVExtensionRegisterCallback(fnc); -// } +// context is new +__declspec(dllexport) void RVExtensionContext(const char **argv, int argc) +{ + goRVExtensionContext(argv, argc); +} +#else +__declspec(dllexport) void __stdcall _RVExtension(char *output, size_t outputSize, char *input) +{ + goRVExtension(output, outputSize, input); +} +__declspec(dllexport) void __stdcall _RVExtensionVersion(char *output, size_t outputSize) +{ + goRVExtensionVersion(output, outputSize); +} + +__declspec(dllexport) void __stdcall _RVExtensionArgs(char *output, size_t outputSize, char *input, char **argv, int argc) +{ + goRVExtensionArgs(output, outputSize, input, argv, argc); +} + +__declspec(dllexport) void __stdcall _RVExtensionRegisterCallback(extensionCallback fnc) +{ + goRVExtensionRegisterCallback(fnc); +} + +// context is new +__declspec(dllexport) void __stdcall _RVExtensionContext(const char **argv, int argc) +{ + goRVExtensionContext(argv, argc); +} +#endif +// do this for all the other exported functions \ No newline at end of file diff --git a/arma.go.bk b/arma.go.bk new file mode 100644 index 0000000..595075a --- /dev/null +++ b/arma.go.bk @@ -0,0 +1,312 @@ +package main + +/* +#include +#include +#include +#include "extensionCallback.h" +*/ +import "C" // This is required to import the C code + +import ( + "context" + "encoding/json" + "fmt" + "io" + "log" + "os" + "strconv" + "strings" + "time" + "unsafe" + + influxdb2 "github.com/influxdata/influxdb-client-go/v2" +) + +var EXTENSION_VERSION string = "0.0.1" +var extensionCallbackFnc C.extensionCallback +var influxConnectionSettings influxSettings + +// configure log output +func init() { + log.SetFlags(log.LstdFlags | log.Lshortfile) + // log to file + f, err := os.OpenFile("rangermetrics.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + log.Fatalf("error opening file: %v", err) + } + // log to console as well + log.SetOutput(io.MultiWriter(f, os.Stdout)) +} + +// func RVExtensionContext(output *C.char, argc *C.int) { + +// } + +type influxSettings struct { + Host string `json:"host"` + Token string `json:"token"` + Org string `json:"org"` + Bucket string `json:"bucket"` +} + +func loadSettings() (dir string, result string, host string) { + // print the current working directory + + var file *os.File + var err error + dir, err = os.Getwd() + if err != nil { + log.Fatal(err) + } + log.Println("getSettings", dir) + // read settings from file + // settings.json should be in the same directory as the .dll + // see if the file exists + if _, err = os.Stat("settings.json"); os.IsNotExist(err) { + // file does not exist + log.Println("settings.json does not exist") + // create the file + file, err = os.Create("settings.json") + if err != nil { + log.Fatal(err) + } + defer file.Close() + // write the default settings to the file + defaultSettings := influxSettings{ + Host: "http://localhost:8086", + Token: "my-token", + Org: "my-org", + Bucket: "my-bucket", + } + encoder := json.NewEncoder(file) + err = encoder.Encode(defaultSettings) + if err != nil { + log.Fatal(err) + } + result = "settings.json created - please modify!" + host = defaultSettings.Host + return dir, result, host + } else { + // file exists + log.Println("settings.json exists") + // read the file + file, err = os.Open("settings.json") + if err != nil { + log.Fatal(err) + } + defer file.Close() + decoder := json.NewDecoder(file) + err = decoder.Decode(&influxConnectionSettings) + if err != nil { + log.Fatal(err) + } + result = "settings.json read" + host = influxConnectionSettings.Host + } + + return dir, result, host +} + +func runExtensionCallback(name *C.char, function *C.char, data *C.char) C.int { + return C.runExtensionCallback(extensionCallbackFnc, name, function, data) +} + +//aexport goRVExtensionVersion +// func goRVExtensionVersion(output *C.char, outputsize C.size_t) { +// return +// result := C.CString(EXTENSION_VERSION) +// defer C.free(unsafe.Pointer(result)) +// var size = C.strlen(result) + 1 +// if size > outputsize { +// size = outputsize +// } +// C.memmove(unsafe.Pointer(output), unsafe.Pointer(result), size) +// } + +//export goRVExtensionArgs +// func goRVExtensionArgs(output *C.char, outputsize C.size_t, input *C.char, argv **C.char, argc C.int) { +// return +// var offset = unsafe.Sizeof(uintptr(0)) +// var out []string +// for index := C.int(0); index < argc; index++ { +// out = append(out, C.GoString(*argv)) +// argv = (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(argv)) + offset)) +// } +// temp := fmt.Sprintf("Function: %s nb params: %d params: %s!", C.GoString(input), argc, out) + +// // Return a result to Arma +// result := C.CString(temp) +// defer C.free(unsafe.Pointer(result)) +// var size = C.strlen(result) + 1 +// if size > outputsize { +// size = outputsize +// } + +// if C.GoString(input) == "sendToInflux" { +// // start a goroutine to send the data to influx +// // param string is argv[0] which is the data to send to influx +// go sendToInflux(out) +// } + +// C.memmove(unsafe.Pointer(output), unsafe.Pointer(result), size) +// // return 1 +// } + +func callBackExample() { + name := C.CString("arma") + defer C.free(unsafe.Pointer(name)) + function := C.CString("funcToExecute") + defer C.free(unsafe.Pointer(function)) + // Make a callback to Arma + for i := 0; i < 3; i++ { + time.Sleep(2 * time.Second) + param := C.CString(fmt.Sprintf("Loop: %d", i)) + defer C.free(unsafe.Pointer(param)) + runExtensionCallback(name, function, param) + } +} + +func sanitize(s string) string { + t := strings.ReplaceAll(s, "\"", "") + return t +} + +func sendToInflux(a3Data []string) { + EXPECTED_PARAMS := 8 + + var logData string + functionName := "sendToInflux" + + if len(a3Data) < EXPECTED_PARAMS { + logData = fmt.Sprintf(`["Not all parameters present (got %d, expected %d)", "ERROR"]`, len(a3Data), EXPECTED_PARAMS) + logLine(functionName, logData, "ERROR") + return + } + + // sanitize all elements + for i, v := range a3Data { + a3Data[i] = sanitize(v) + } + + host := influxConnectionSettings.Host + token := influxConnectionSettings.Token + org := influxConnectionSettings.Org + bucket := influxConnectionSettings.Bucket + profile, locality := a3Data[0], a3Data[1] + missionName, worldName, serverName := a3Data[2], a3Data[3], a3Data[4] + metric := a3Data[5] + valueType := a3Data[6] + + tags := map[string]string{ + "profile": profile, + "locality": locality, + "worldName": worldName, + "serverName": serverName, + } + fields := map[string]interface{}{ + "missionName": missionName, + // "count": value, + } + + // parse the value + var err error + // allow for float or int values, but remove any auto backslashes + // check if includes certain strings + if strings.Contains(valueType, "float") { + fields["count"], err = strconv.ParseFloat(sanitize(a3Data[7]), 64) + } else if strings.Contains(valueType, "int") { + fields["count"], err = strconv.Atoi(sanitize(a3Data[7])) + } else { + logData = fmt.Sprintf("valueType must be 'float' or 'int': %s, %s, %s", metric, valueType, a3Data[7]) + logLine(functionName, logData, "ERROR") + return + } + + if err != nil { + logData = fmt.Sprintf("Error parsing value: %s", err.Error()) + logLine(functionName, logData, "ERROR") + return + } + + // influxDB init + client := influxdb2.NewClientWithOptions(host, token, influxdb2.DefaultOptions().SetBatchSize(120)) + writeAPI := client.WriteAPIBlocking(org, bucket) + + p := influxdb2.NewPoint(metric, tags, fields, time.Now()) + + // write synchronously + err = writeAPI.WritePoint(context.Background(), p) + + if err != nil { + logData = fmt.Sprintf("Error writing to InfluxDB: %s", err.Error()) + logLine(functionName, logData, "ERROR") + } + + defer client.Close() + + logData = fmt.Sprintf("Sent to Influx: %s, %s", metric, a3Data[7]) + logLine(functionName, logData, "INFO") +} + +func logLine(functionName string, data string, resultType string) { + statusName := C.CString("RangerMetrics") + defer C.free(unsafe.Pointer(statusName)) + statusFunction := C.CString(functionName) + defer C.free(unsafe.Pointer(statusFunction)) + statusParam := C.CString(fmt.Sprintf(`["%s", "%s"]`, data, resultType)) + defer C.free(unsafe.Pointer(statusParam)) + runExtensionCallback(statusName, statusFunction, statusParam) + + log.Println(data) +} + +//export goRVExtension +func goRVExtension(output *C.char, outputsize C.size_t, input *C.char) { + temp := fmt.Sprintf("Hello %s!", C.GoString(input)) + // Return a result to Arma + result := C.CString(temp) + defer C.free(unsafe.Pointer(result)) + var size = C.strlen(result) + 1 + if size > outputsize { + size = outputsize + } + C.memmove(unsafe.Pointer(output), unsafe.Pointer(result), size) + + // var temp string + + // logLine("goRVExtension", fmt.Sprintf("Input: %s", C.GoString(input)), "INFO") + + // switch C.GoString(input) { + // case "version": + // temp = fmt.Sprintf("%s", EXTENSION_VERSION) + // case "loadSettings": + // cwd, result, influxHost := loadSettings() + // log.Println("CWD:", cwd) + // log.Println("RESULT:", result) + // log.Println("INFLUX HOST:", influxHost) + // if result != "" { + // temp = fmt.Sprintf(`["CWD: %s", "RESULT: %s", "%s"]`, cwd, result, influxHost) + // } + // default: + // temp = fmt.Sprintf(`["ERR", "Unknown command: %s", "ERR"]`, C.GoString(input)) + // } + + // result := C.CString(temp) + // defer C.free(unsafe.Pointer(result)) + // var size = C.strlen(result) + 1 + // if size > outputsize { + // size = outputsize + // } + + // C.memmove(unsafe.Pointer(output), unsafe.Pointer(result), size) + // return +} + +//aexport goRVExtensionRegisterCallback +// func goRVExtensionRegisterCallback(fnc C.extensionCallback) { +// return +// extensionCallbackFnc = fnc +// } + +func main() {} diff --git a/basictest.a b/basictest.a new file mode 100644 index 0000000..f4cbff3 Binary files /dev/null and b/basictest.a differ diff --git a/arma.go b/basictest.go similarity index 55% rename from arma.go rename to basictest.go index 2daf304..6d2f5c8 100644 --- a/arma.go +++ b/basictest.go @@ -11,14 +11,8 @@ import "C" import ( "fmt" - "log" - "os" - "strconv" - "strings" "time" "unsafe" - - influxdb2 "github.com/influxdata/influxdb-client-go/v2" ) var extensionCallbackFnc C.extensionCallback @@ -29,7 +23,7 @@ func runExtensionCallback(name *C.char, function *C.char, data *C.char) C.int { //export goRVExtensionVersion func goRVExtensionVersion(output *C.char, outputsize C.size_t) { - result := C.CString("Version 0.0.1") + result := C.CString("Version 1.0") defer C.free(unsafe.Pointer(result)) var size = C.strlen(result) + 1 if size > outputsize { @@ -38,8 +32,20 @@ func goRVExtensionVersion(output *C.char, outputsize C.size_t) { C.memmove(unsafe.Pointer(output), unsafe.Pointer(result), size) } +//export goRVExtensionContext +func goRVExtensionContext(argv **C.char, argc C.int) { + var offset = unsafe.Sizeof(uintptr(0)) + var out []string + for index := C.int(0); index < argc; index++ { + out = append(out, C.GoString(*argv)) + argv = (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(argv)) + offset)) + } + fmt.Printf("Context: %s", out) + C.memmove(unsafe.Pointer(argv), unsafe.Pointer(&out), C.size_t(offset)) +} + //export goRVExtensionArgs -func goRVExtensionArgs(output *C.char, outputsize C.size_t, input *C.char, argv **C.char, argc C.int) int { +func goRVExtensionArgs(output *C.char, outputsize C.size_t, input *C.char, argv **C.char, argc C.int) { var offset = unsafe.Sizeof(uintptr(0)) var out []string for index := C.int(0); index < argc; index++ { @@ -56,11 +62,10 @@ func goRVExtensionArgs(output *C.char, outputsize C.size_t, input *C.char, argv size = outputsize } C.memmove(unsafe.Pointer(output), unsafe.Pointer(result), size) - return 1 } func callBackExample() { - name := C.CString("arma") + name := C.CString("armago") defer C.free(unsafe.Pointer(name)) function := C.CString("funcToExecute") defer C.free(unsafe.Pointer(function)) @@ -73,77 +78,6 @@ func callBackExample() { } } -func sendToInflux(data string) { - - a3Data := strings.Split(data, ",") - - host := a3Data[0] - token := a3Data[1] - org := a3Data[2] - bucket := a3Data[3] - profile, locality := a3Data[4], a3Data[5] - missionName, worldName, serverName := a3Data[6], a3Data[7], a3Data[8] - metric := a3Data[9] - valueType := a3Data[10] - - tags := map[string]string{ - "profile": profile, - "locality": locality, - "worldName": worldName, - "serverName": serverName, - } - fields := map[string]interface{}{ - "missionName": missionName, - // "count": value, - } - - var err error - // allow for float or int values - if valueType == "float" { - fields["count"], err = strconv.ParseFloat(a3Data[11], 64) - } else if valueType == "int" { - fields["count"], err = strconv.Atoi(a3Data[11]) - } - - if (valueType != "float") && (valueType != "int") { - log.Println("valueType must be either 'float' or 'int'", metric, valueType, a3Data[11]) - } - - if err != nil { - log.Println(err) - } - - // int_value, err := strconv.Atoi(value) - client := influxdb2.NewClient(host, token) - writeAPI := client.WriteAPI(org, bucket) - - p := influxdb2.NewPoint( - metric, - tags, - fields, - time.Now(), - ) - - // write point asynchronously - writeAPI.WritePoint(p) - - // Flush writes - writeAPI.Flush() - - defer client.Close() - - f, err := os.OpenFile("a3metrics.log", - os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - log.Println(err) - } - defer f.Close() - - //logger := log.New(f, "", log.LstdFlags) - //logger.Println(err) - -} - //export goRVExtension func goRVExtension(output *C.char, outputsize C.size_t, input *C.char) { // Return by default through ExtensionCallback arma handler the result @@ -151,17 +85,13 @@ func goRVExtension(output *C.char, outputsize C.size_t, input *C.char) { go callBackExample() } else { // Return a result through callextension Arma call - temp := fmt.Sprintf("Rangermetrics: %s", C.GoString(input)) + temp := fmt.Sprintf("Hello %s!", C.GoString(input)) result := C.CString(temp) defer C.free(unsafe.Pointer(result)) var size = C.strlen(result) + 1 if size > outputsize { size = outputsize } - - // start a goroutine to send the data to influx - go sendToInflux(C.GoString(input)) - C.memmove(unsafe.Pointer(output), unsafe.Pointer(result), size) } } diff --git a/basictest.h b/basictest.h new file mode 100644 index 0000000..7ddcf8d --- /dev/null +++ b/basictest.h @@ -0,0 +1,94 @@ +/* Code generated by cmd/cgo; DO NOT EDIT. */ + +/* package command-line-arguments */ + + +#line 1 "cgo-builtin-export-prolog" + +#include + +#ifndef GO_CGO_EXPORT_PROLOGUE_H +#define GO_CGO_EXPORT_PROLOGUE_H + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef struct { const char *p; ptrdiff_t n; } _GoString_; +#endif + +#endif + +/* Start of preamble from import "C" comments. */ + + +#line 3 "basictest.go" + +#include +#include +#include + +#include "extensionCallback.h" + +#line 1 "cgo-generated-wrapper" + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef size_t GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +#ifdef _MSC_VER +#include +typedef _Fcomplex GoComplex64; +typedef _Dcomplex GoComplex128; +#else +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; +#endif + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef _GoString_ GoString; +#endif +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern __declspec(dllexport) void RVExtensionVersion(char* output, size_t outputsize); +extern __declspec(dllexport) void RVExtensionContext(char** argv, int argc); +extern __declspec(dllexport) void RVExtensionArgs(char* output, size_t outputsize, char* input, char** argv, int argc); +extern __declspec(dllexport) void RVExtension(char* output, size_t outputsize, char* input); +extern __declspec(dllexport) void RVExtensionRegisterCallback(extensionCallback fnc); + +#ifdef __cplusplus +} +#endif diff --git a/basictest_x64.h b/basictest_x64.h new file mode 100644 index 0000000..ed18d34 --- /dev/null +++ b/basictest_x64.h @@ -0,0 +1,94 @@ +/* Code generated by cmd/cgo; DO NOT EDIT. */ + +/* package arma.go */ + + +#line 1 "cgo-builtin-export-prolog" + +#include + +#ifndef GO_CGO_EXPORT_PROLOGUE_H +#define GO_CGO_EXPORT_PROLOGUE_H + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef struct { const char *p; ptrdiff_t n; } _GoString_; +#endif + +#endif + +/* Start of preamble from import "C" comments. */ + + +#line 3 "basictest.go" + +#include +#include +#include + +#include "extensionCallback.h" + +#line 1 "cgo-generated-wrapper" + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef size_t GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +#ifdef _MSC_VER +#include +typedef _Fcomplex GoComplex64; +typedef _Dcomplex GoComplex128; +#else +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; +#endif + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef _GoString_ GoString; +#endif +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern __declspec(dllexport) void goRVExtensionVersion(char* output, size_t outputsize); +extern __declspec(dllexport) void goRVExtensionContext(char** argv, int argc); +extern __declspec(dllexport) void goRVExtensionArgs(char* output, size_t outputsize, char* input, char** argv, int argc); +extern __declspec(dllexport) void goRVExtension(char* output, size_t outputsize, char* input); +extern __declspec(dllexport) void goRVExtensionRegisterCallback(extensionCallback fnc); + +#ifdef __cplusplus +} +#endif diff --git a/build.txt b/build.txt new file mode 100644 index 0000000..b4bda1e --- /dev/null +++ b/build.txt @@ -0,0 +1,40 @@ +$ENV:GOARCH = "amd64" +$ENV:CGO_ENABLED = 1 +# # $ENV:CC = "C:`\Program Files (x86)`\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\cl.exe" +go build -o RangerMetrics_x64.dll -buildmode=c-shared . +go build -buildmode=c-shared . +. "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\dumpbin.exe" /exports .\RangerMetrics_x64.dll + + +go build -buildmode=c-archive basictest.go +gcc -shared -pthread -o basictest_x64.dll RVExtension.c basictest.a + +g++ -o test -l mingw32 RVExtension.c .\RangerMetrics_x64.dll + + +go build -buildmode=c-archive arma.go +gcc -shared -pthread -o RangerMetrics_x64.dll RVExtension.c arma.a -lWinMM -lntdll -lWS2_32 + + + + + +$ENV:GOARCH = 386 +$ENV:CGO_ENABLED = 1 +go build -buildmode=c-archive basictest.go +gcc -shared -pthread -o basictest_x64.dll -fPIC RVExtension.c basictest.a + +$ENV:GOARCH = "amd64" +$ENV:CGO_ENABLED = 1 +go build -buildmode=c-archive basictest_x64.go +gcc -shared -pthread -o basictest_x64.dll -fPIC RVExtension.c basictest_x64.a + +$ENV:GOARCH = 386 +$ENV:CGO_ENABLED = 1 +go build -o basictest.dll -buildmode=c-shared . +. "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\dumpbin.exe" /exports .\basictest.dll + +$ENV:GOARCH = "amd64" +$ENV:CGO_ENABLED = 1 +go build -o basictest_x64.dll -buildmode=c-shared basictest.go +. "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\dumpbin.exe" /exports .\basictest_x64.dll \ No newline at end of file diff --git a/callExtension.exe b/callExtension.exe new file mode 100644 index 0000000..a4b9e74 Binary files /dev/null and b/callExtension.exe differ diff --git a/callExtension_x64.exe b/callExtension_x64.exe new file mode 100644 index 0000000..f2c652c Binary files /dev/null and b/callExtension_x64.exe differ diff --git a/extensionCallback.h b/extensionCallback.h index b66ab5f..1381732 100644 --- a/extensionCallback.h +++ b/extensionCallback.h @@ -5,6 +5,7 @@ typedef int (*extensionCallback)(char const *name, char const *function, char const *data); /* https://golang.org/cmd/cgo/#hdr-C_references_to_Go */ -static inline int runExtensionCallback(extensionCallback fnc, char const *name, char const *function, char const *data) { +static inline int runExtensionCallback(extensionCallback fnc, char const *name, char const *function, char const *data) +{ return fnc(name, function, data); } \ No newline at end of file diff --git a/go.mod b/go.mod index 1b5388b..f1c1aed 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,3 @@ module arma.go go 1.20 require github.com/influxdata/influxdb-client-go/v2 v2.12.3 - -require ( - github.com/deepmap/oapi-codegen v1.8.2 // indirect - github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect - github.com/pkg/errors v0.9.1 // indirect - golang.org/x/net v0.7.0 // indirect -) diff --git a/go.sum b/go.sum index 4cdf8a4..dec5d5c 100644 --- a/go.sum +++ b/go.sum @@ -36,24 +36,33 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -65,18 +74,30 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/makefile b/makefile index 6486227..6320384 100644 --- a/makefile +++ b/makefile @@ -1,12 +1,12 @@ build: - $env:GOARCH="amd64" - $env:CGO_ENABLED=1 + export GOARCH="amd64" + export CGO_ENABLED=1 go build -o RangerMetrics_x64.so -buildmode=c-shared . - $env:GOARCH = "386" - $env:CGO_ENABLED = 1 + export GOARCH = "386" + export CGO_ENABLED = 1 go build -o RangerMetrics.dll -buildmode=c-shared . - $env:GOARCH = "amd64" - $env:CGO_ENABLED = 1 + export GOARCH = "amd64" + export CGO_ENABLED = 1 go build -o RangerMetrics_x64.dll -buildmode=c-shared . diff --git a/settings.json.example b/settings.json.example new file mode 100644 index 0000000..4a3c403 --- /dev/null +++ b/settings.json.example @@ -0,0 +1,6 @@ +{ + "host" : "http://INFLUX_URL:8086", + "token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX_AUTH_TOKEN_XXXXXXXXXXXXXXXXXXXXXXXXXXX", + "org" : "ORG_NAME", + "bucket" : "BUCKET_NAME", +} \ No newline at end of file diff --git a/testsqf.sqf b/testsqf.sqf new file mode 100644 index 0000000..014aa96 --- /dev/null +++ b/testsqf.sqf @@ -0,0 +1,25 @@ +// freeExtension "RangerMetrics"; +// sleep 0.5; +// "RangerMetrics" callExtension "loadSettings"; +// sleep 0.5; +// "RangerMetrics" callextension "version"; +// sleep 1.5; +// "RangerMetrics" callExtension ["sendToInflux", ["myProfile","global","TestMission123","Altis","TestingServer","units.count","int","22"]]; + +// sleep 12; +// freeExtension "RangerMetrics"; + + +freeExtension "basictest"; +sleep 0.5; +"basictest" callExtension "loadSettings"; +sleep 0.5; +"basictest" callextension "version"; +sleep 1.5; +"basictest" callExtension ["sendToInflux", ["myProfile","global","TestMission123","Altis","TestingServer","units.count","int","22"]]; + +sleep 12; +freeExtension "basictest"; + +// sleep 15; +// exit; \ No newline at end of file