I would like to send a message to Bouyomi-Chan on Windows using interprocess communication.
So I wrote the following code.
import winim
var cds: ref COPYDATASTRUCT
cds.dwData = 0
cds.lpData = ref "Hello World"
cds.cbData = len(cds.lpData) + 1
# 13436904 is test handle
let result = SendMessage(HWND(13436904), WM_COPYDATA, 0, LPARAM(cds));
echo result
However, errors occur in cds.lpData = ref "Hello World", cds.cbData = len(cds.lpData) + 1 and LPARAM(cds).
cds.lpData = ref "Hello World" ' s error:
type mismatch: got <type ref Error Type> but expected 'PVOID = pointer'
cds.cbData = len(cds.lpData) + 1' s error:
ype mismatch: got <PVOID>
but expected one of:
proc len(s: mstring): int
first type mismatch at position: 1
let result = SendMessage(HWND(13436904), WM_COPYDATA, 0, LPARAM(cds));'s error:
type mismatch: got <ref COPYDATASTRUCT> but expected 'LPARAM = int64'
How should I match these types? Please let me know if anyone knows.
Thank you.
Try this
var cds: COPYDATASTRUCT
cds.dwData = 0
cds.lpData = "Hello World"
cds.cbData = len(cds.lpData) + 1
I think it must look like this:
# For Reference
# COPYDATASTRUCT* {.pure.} = object
# dwData*: ULONG_PTR
# cbData*: DWORD
# lpData*: PVOID
# https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-copydatastruct
# cbData
# Type: DWORD
# The size, in bytes, of the data pointed to by the lpData member.
import winim
var mydata: cstring = "Hello World"
var cds: COPYDATASTRUCT
cds.dwData = 0
cds.lpData = addr mydata # addr gets a pointer to the mydata cstring
cds.cbData = mydata.len.DWORD
since lpData is a pointer the "size" of the pointer makes no sense here (since it will always be 32/64 bit).
you should ask the maintainer of that package and check the docs to see if there's a nicer api for you. for example they provide converters from Nim strings to the various types of windows strings, and i don't know which one you need.
check the manual again on the difference between refs and ptrs when interfacing with a c library you'll want to be sending ptr types.
it's hard to know what the receiving application is expecting, but a cstring (LPSTR) cast to void would be a reasonable guess? i don't know, i'd expect wide chars for a japanese text-to-speech app.
but let's say it's a cstring. in that case you'd want
var message = "Hello,World".cstring
var cds = COPYDATASTRUCT(dwData: 0,#???
lpData: cast[pointer](message),#or message[0].addr
cbData: message.len + 1 #careful if message is wide char
)
let result = SendMessage(HWND(13436904),WM_COPYDATA,cast[LPARAM](cds.addr))
If you just want to synthesize japanese speech from japanese text, nimopenjtalk can do that. It is Open JTalk and hts_engine API bindings for Nim. You can get wav file or wave data by calling Nim procedures with UTF8 string.
This example code just synthesizes speech from a Nim string: https://github.com/demotomohiro/nimopenjtalk/blob/master/examples/speechSynthWave.nim
This example code take text from stdin and play the synthesized speech using openAL: https://github.com/demotomohiro/nimopenjtalk/blob/master/examples/speechSynthOpenAL.nim
Thank you everyone for an answer.
I wrote the code referring to the answer from @shirleyquirk and it worked properly! Thank you very much.
Also, thank you for the interesting information, @demotomohiro. Let me see this, too.