Issue with sys package related to I/O operation - windows

As I want to access some lower-level API to do I/O operation using CreateFile function
syscall.CreateFile( name *uint16…)
While doing so I face a problem that the name parameter is of *uint16 but it should be an array ([]uint16) so that it can handle the string in the UTF-16 format. As we can see in the example provided by Microsoft -> link where TEXT macro convert the string into wchar_t array or we can say []uint16.
Thanks in advance and sorry if I said anything wrong as I’m just a toddler in this field.
(Solution 1)
func UTF16PtrFromString(s string) (*uint16, error)
Built-in encoder which returns a pointer to the UTF-16 encoding
(Solution 2)
As previously I was unaware of Solution 1 so I wrote my own function which does the exact work so you can ignore this solution
For passing the file name (string) to the sys package we have to first convert the string to an array of UTF-16 and pass the pointer of the first element
var srcUTf16 [ ]uint16 = utf16.Encode([ ]rune(src+ "\x00"))
syscall.CreateFile(&srcUTf16[0],..... )
Edit:-Adding solution
Edit:- Adding correct solution and adding Terminating NUL in solution 2.

I don't really care for Windows API function signatures Go has made, and I have written about this. So if you want, you can write your own. Make a file like this:
//go:generate mkwinsyscall -output zfile.go file.go
//sys createFile(name string, access int, mode int, sec *windows.SecurityAttributes, disp int, flag int, template int) (hand int, err error) = kernel32.CreateFileW
package main
import "golang.org/x/sys/windows"
func main() {
n, e := createFile(
"file.txt",
windows.GENERIC_READ,
0,
nil,
windows.CREATE_NEW,
windows.FILE_ATTRIBUTE_NORMAL,
0,
)
if e != nil {
panic(e)
}
println(n)
}
Then build:
go mod init file
go generate
go mod tidy
go build
I know the result works, because it returns a valid handle the first time, and invalid handle the second time (also because a file is created of course):
PS C:\> .\file.exe
336
PS C:\> .\file.exe
-1
If you want, you can edit the signature line I put above, to suit your needs.

Related

Write fixed length padded lines to file Go

For printing, justified and fixed length, seems like what everyone asks about and there are many examples that I have found, like...
package main
import "fmt"
func main() {
values := []string{"Mustang", "10", "car"}
for i := range(values) {
fmt.Printf("%10v...\n", values[i])
}
for i := range(values) {
fmt.Printf("|%-10v|\n", values[i])
}
}
Situation
But what if I need to WRITE to a file with fixed length bytes?
For example: what if I have requirement that states, write this line to a file that must be 32 bytes, left justified and padded to the right with 0's
Question
So, how do you accomplish this when writing to a file?
There are analogous functions to fmt.PrintXX() functions, ones that start with an F, take the form of fmt.FprintXX(). These variants write the result to an io.Writer which may be an os.File as well.
So if you have the fmt.Printf() statements which you want to direct to a file, just change them to call fmt.Fprintf() instead, passing the file as the first argument:
var f *os.File = ... // Initialize / open file
fmt.Fprintf(f, "%10v...\n", values[i])
If you look into the implementation of fmt.Printf():
func Printf(format string, a ...interface{}) (n int, err error) {
return Fprintf(os.Stdout, format, a...)
}
It does exactly this: it calls fmt.Fprintf(), passing os.Stdout as the output to write to.
For how to open a file, see How to read/write from/to file using Go?
See related question: Format a Go string without printing?

Return all contents within an object

I am very new to Go, so I am sorry for that noob question.
In JavaScript console.log(window) returns all objects inside of window. In PHP var_dump(new DateTime()) returns all objects inside of DateTime().
Is there a function in Go that will return all objects from a given object? For example Println should be returned if fmt is given.
Try executing go doc fmt in a terminal to produce a description of the "fmt" package and a listing of the functions it exports, or referring to the fmt package documentation at https://golang.org. In go, as in most other static/compiled languages, users are expected to refer to documentation (or docs) which describe the programming language and its libraries. Contrast this to some dynamic/scripting languages, which often make it easy to query any object to discover its usable properties.
At runtime, you can get a helpful printout of any arbitrary value by using the %#v formatting verb to produce a go syntax representation of the value, e.g.
xs := []int{1, 2, 3}
fmt.Printf("OK: xs=%#v\n", xs)
// OK: xs=[]int{1, 2, 3}
Note that the package "fmt" is not a value in the go language so it cannot be printed at runtime as such.
In Go is possible does something similar, but don't work for all.
func main() {
//arrays
a := []int{1,2,3,4}
fmt.Printf("%v\r\n", a) //print [1 2 3 4]
//maps
b := map[string]int{
"a":1,
"b":2,
}
fmt.Printf("%v\r\n", b) //print map[a:1 b:2]
//structs
c := struct{
A int
B int
}{1,2}
d := struct{
C struct{
A int
B int
}
D int
}{c,2}
fmt.Printf("%v\r\n", d) //print {{1 2} 2}
}
See in: https://play.golang.org/p/vzlCsOG497h
If you pass fmt occurs error because it is a package. The error is:
Error: use of package fmt without selector
I hope this helps (too)!
GO OOP, & inheritance
Go does not have objects, but we do have custom types and interfaces that we can attach attributes, functions and other types to.
What specifically are you trying to do? If you're looking for a var_dump:
USING fmt.Println
someErr := fmt.Errorf("custom type error")
fmt.Println(someErr)
Println formats using the default formats for its operands and writes to standard output.
USING fmt.Printf
someErr := fmt.Errorf("custom type error")
fmt.Printf("This is an error:%v A num: %v A str", someErr, 19, "Stackoverflow")
Printf formats according to a format specifier and writes to standard output.
USING fmt.Sprintf
someErr := fmt.Errorf("custom type error")
// someStr now contains the string formatted as shown below
someStr := fmt.Sprintf("This is an error:%v A num: %v A str", someErr, 19, "Stackoverflow")
Sprintf formats according to a format specifier and returns the resulting string.
Here is an example of my personal preference when outputting var data:
https://play.golang.org/p/8dpeE-fray_J
I hope this helps!

How to return a string from JSON to a C caller (Golang CGO)?

I'm trying to develop a routine in Go that will be called by a C++ program. The Go looks like the following:
package main
import (
"C"
"encoding/json"
"log"
)
type keydata struct {
Key string `json:"key"`
Error string `json:"Error"`
}
func lookupKey() string {
//simplified to remove the call to web service
body := "{\"key\": \"blahblah\", \"Error\": \"\"}"
k := keydata{}
err := json.Unmarshal([]byte(body), &k)
if err != nil {
log.Fatal(err)
}
return k.Key
}
//export GetKey
func GetKey() string {
theKey := lookupKey()
return theKey
}
func main() {}
If I substitute some hard coded value for the return k.Key statement everything works fine and the C or C++ can call the exported GetKey function. When I try to return the decoded JSON string from k.Key or even just return the string from the variable named body - I receive an error:
runtime error: cgo result has Go pointer
goroutine 17 [running, locked to thread]
I'm building this as follows:
go build -buildmode=c-archive example.go
The C++ is built as follow:
g++ -pthread test.cpp example.a -o test
What am I missing to make this work without raising a panic error? I'm digging around to find an answer but have yet to resolve this.
#JimB & #Jsor, thank you so much for your responses. Returning a *C.char certainly worked. I'm left wondering though, when I return it as a Go string behind the scenes in the auto generated header file Go actually creates and passes a C struct named GoString that contains a char array named p and the length named n. As long as I pass a hard-coded string instead of k.Key it actually works and I can interrogate the auto-generated char array in C++. When I try to return k.Key, a string it throws that exception. Is it possible to cast the Go string or add some notation to the export decoration to make it work?
I can certainly return the C.CString char array and make it work - thank you! I'm just also wanting to understand why it works when returning a hard coded string and not in the example I've posted.
Thank you both for your time and explanations.
You can't return a Go string to a C function. If you want a C string, you can use the C.CString function to create one and return a *C.char
//export GetKey
func GetKey() *C.char {
theKey := lookupKey()
return C.CString(theKey)
}
The return value from this function must be explicitly freed in the C code.
If freeing the allocated buffer isn't convenient, its common to fill a buffer provided by the caller:
func GetKey(buff *C.char, n int) int
If you can allocate the memory but don't want to handle C strings, you can insert the buffer into a pointer and return the size.
func GetKey(buff **C.char) int
You need to use C.CString to convert Go strings to raw pointers to C strings. Note that C Strings are not garbage collected and must be freed by you elsewhere in the program.
This will make the return type *C.char which should be visible to C as a char array. It will also be your responsibility to return the buffer length (whether your write a separate function or a C struct to do that is up to you).

How to evaluate external go source code "dynamically"?

I need to parse a Go source code file, find a specific type (by name) and use it in my program.
I already managed to find the type I need using the go/ast package but I don't know how to "load" it into my program so that I can use it.
Question: What's the best way to extract and use a type from an external source code file and use it on runtime?
I can't think of anything except an ugly method to basically copy the file, modify it by injecting a "main" function with my encoding stuff which sends the result to stdOut, execute the it, collect the encoded data from stdout, delete the modified file.
Use case: Analyse go source code and encode the types in a specific format (e.g. json schema)
Edit:
Here is some code. The question is how to encode type allTypes (zero value) and then print it.
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"encoding/json"
)
var src string = `
package mypack
type allTypes struct{
Brands Brands
Colours Colours
}
type Brands struct{
Sony string
Apple string
}
type Colours struct{
Red string
Green string
}
`
type sometype struct{
Nothing int
}
func main() {
// src is the input for which we want to inspect the AST.
// Create the AST by parsing src.
fset := token.NewFileSet() // positions are relative to fset
f, err := parser.ParseFile(fset, "src.go", src, 0)
if err != nil {
panic(err)
}
// Inspect the AST and find our function
var tp ast.TypeSpec
ast.Inspect(f, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.TypeSpec:
if x.Name.Name == "allTypes"{
tp = *x
}
}
return true
})
fmt.Printf("We found the type: it is %v", tp)
// Encode the zero value of sometype
x := sometype{}
b, _ := json.Marshal(&x)
fmt.Printf("\n Zero value of someType (json) %s", b)
//Next/Question: How to encode the zero value of "allTypes" ???
}
Also on playground
If I understand you are asking for dynamic type loading ala Java's Class.forName(String className). The short answer is Go doesn't support this.
The correct way, as Nick Johnson pointed out, is to parse the tree using ast, and then "generate" the JSON yourself. You will not be able to "load" the type and use JSON.Marshal. It is also worth noting that any type which supports the json.Marshaler interface may generate custom JSON. You also need to ignore, but mark optional "omitempty" behavior. This really prevents you from using the compile it and hack through "stdout" behavior as well.
If you need to extract type information at runtime, you need to use the reflect package. This is the way Go's encoding/json and other similar packages work.
If you want to operate on the types defined in a Go source file, you can use the go.parser package to read and parse a source file into an AST, then traverse the AST for the elements you want to examine.
It seems there is no way to load the type information extracted from the source code(please correct me if I'm wrong). The only solution is to create/generate a package (main), inject it with all the types extracted from the target source code file, build/compile it, execute it and collect the encoded data from stdout.

Using Golang to get Windows idle time (GetLastInputInfo or similar)

Is there an example or method of getting a Windows system's idle time using Go?
I've been looking at the documentation at the Golang site but I think I'm missing how to access (and use) the API to get system information including the idle time.
Go's website is hardcoded to show the documentation for the standard library packages on Linux. You will need to get godoc and run it yourself:
go get golang.org/x/tools/cmd/godoc
godoc --http=:6060
then open http://127.0.0.1:6060/ in your web browser.
Of note is package syscall, which provides facilities for accessing functions in DLLs, including UTF-16 helpers and callback generation functions.
Doing a quick recursive search of the Go tree says it doesn't have an API for GetLastInputInfo() in particular, so unless I'm missing something, you should be able to call that function from the DLL directly:
user32 := syscall.MustLoadDLL("user32.dll") // or NewLazyDLL() to defer loading
getLastInputInfo := user32.MustFindProc("GetLastInputInfo") // or NewProc() if you used NewLazyDLL()
// or you can handle the errors in the above if you want to provide some alternative
r1, _, err := getLastInputInfo.Call(uintptr(arg))
// err will always be non-nil; you need to check r1 (the return value)
if r1 == 0 { // in this case
panic("error getting last input info: " + err.Error())
}
Your case involves a structure. As far as I know, you can just recreate the structure flat (keeping fields in the same order), but you must convert any int fields in the original to int32, otherwise things will break on 64-bit Windows. Consult the Windows Data Types page on MSDN for the appropriate type equivalents. In your case, this would be
var lastInputInfo struct {
cbSize uint32
dwTime uint32
}
Because this (like so many structs in the Windows API) has a cbSize field that requires you to initialize it with the size of the struct, we must do so too:
lastInputInfo.cbSize = uint32(unsafe.Sizeof(lastInputInfo))
Now we just need to pass a pointer to that lastInputInfo variable to the function:
r1, _, err := getLastInputInfo.Call(
uintptr(unsafe.Pointer(&lastInputInfo)))
and just remember to import syscall and unsafe.
All args to DLL/LazyDLL.Call() are uintptr, as is the r1 return. The _ return is never used on Windows (it has to do with the ABI used).
Since I went over most of what you need to know to use the Windows API in Go that you can't gather from reading the syscall docs, I will also say (and this is irrelevant to the above question) that if a function has both ANSI and Unicode versions, you should use the Unicode versions (W suffix) and the UTF-16 conversion functions in package syscall for best results.
I think that's all the info you (or anyone, for that matter) will need to use the Windows API in Go programs.
Regarding for answer from andlabs. This is ready for use example:
import (
"time"
"unsafe"
"syscall"
"fmt"
)
var (
user32 = syscall.MustLoadDLL("user32.dll")
kernel32 = syscall.MustLoadDLL("kernel32.dll")
getLastInputInfo = user32.MustFindProc("GetLastInputInfo")
getTickCount = kernel32.MustFindProc("GetTickCount")
lastInputInfo struct {
cbSize uint32
dwTime uint32
}
)
func IdleTime() time.Duration {
lastInputInfo.cbSize = uint32(unsafe.Sizeof(lastInputInfo))
currentTickCount, _, _ := getTickCount.Call()
r1, _, err := getLastInputInfo.Call(uintptr(unsafe.Pointer(&lastInputInfo)))
if r1 == 0 {
panic("error getting last input info: " + err.Error())
}
return time.Duration((uint32(currentTickCount) - lastInputInfo.dwTime)) * time.Millisecond
}
func main() {
t := time.NewTicker(1 * time.Second)
for range t.C {
fmt.Println(IdleTime())
}
}
This is code print idle time every second. Try run and don't touch mouse/keyboard

Resources