Closed 5k3105 closed 7 years ago
FWIW, adding -ccdefs
solves the problem here (Linux):
jnml@4670:~/src/github.com/5k3105/NIDAQmx$ cgogen nidaqmx.yml
processing nidaqmx.yml ⠙[ERR] NIDAQmx.h:85:29: unexpected identifier int64, expected one of ['(', ')', ',', ':', ';', '=', '[', '{', _Bool, _Complex, _Noreturn, _Static_assert, asm, auto, char, const, double, enum, extern, float, inline, int, long, register, restrict, short, signed, static, struct, typedef, typedefname, typeof, union, unsigned, void, volatile]
jnml@4670:~/src/github.com/5k3105/NIDAQmx$ cgogen -ccdefs nidaqmx.yml
processing nidaqmx.yml done.
jnml@4670:~/src/github.com/5k3105/NIDAQmx$ ll nidaqmx
celkem 196
-rw-rw-r-- 1 jnml jnml 277 lis 19 01:29 cgo_helpers.h
-rw-rw-r-- 1 jnml jnml 187050 lis 19 01:29 const.go
-rw-rw-r-- 1 jnml jnml 294 lis 19 01:29 doc.go
-rw-rw-r-- 1 jnml jnml 302 lis 19 01:29 nidaqmx.go
jnml@4670:~/src/github.com/5k3105/NIDAQmx$
Did not work for me. Gave same error. Win7. I have TDM-GCC64 installed.
cgogen -ccdefs C:\goworksp\src\local\NIDAQmx\nidaqmx.yml
Thank you for responding
Sorry to hear that it did not help. Possibly related cznic/cc#58 which has a pending PR cznic/cc#60.
@5k3105 Hi! A really quick fix would be to define __linux__
so the header won't be relying on compiler-specific types. Borrowing all compiler defines for this case is like using a sledgehammer for cracking nuts.
PARSER:
SourcesPaths: ["NIDAQmx.h"]
Defines:
__linux__: 1
Please close the issue if this helps. @cznic probably right, borrowing defines from compiler not yet available on windows.
@5k3105 also, your translator rules look messed up a bit, check out these:
TRANSLATOR:
ConstRules:
defines: expand
Rules:
global:
- {action: accept, from: "^DAQmx"}
- {action: replace, from: "^DAQmx"}
- {transform: export}
post-global:
- {action: replace, from: _$}
- {load: snakecase}
works beautifully
Wow guys! Thanks a lot! Generated this time :+1:
I'll let you know how it tests monday - thanks so much :)
Hi,
package main
import (
"fmt"
"local/nidaqmx"
)
const DAQMX_DEVICE_NAME = "cDAQ9181-184F222"
func main() {
fmt.Println(nidaqmx.SelfTestDevice(DAQMX_DEVICE_NAME))
}
I get:
λ go build main.go
# local/NIDAQmx
In file included from ..\NIDAQmx\cgo_helpers.go:9:0:
./NIDAQmx.h:85:10: error: unknown type name '__int64'
typedef __int64 int64;
^
./NIDAQmx.h:93:29: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'uInt64'
typedef unsigned __int64 uInt64;
^
In file included from ..\NIDAQmx\cgo_helpers.go:9:0:
./NIDAQmx.h:2652:145: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxCfgSampClkTiming (TaskHandle taskHandle, const char source[], float64 rate, int32 activeEdge, int32 sampleMode, uInt64 sampsPerChan);
^
./NIDAQmx.h:2654:92: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxCfgHandshakingTiming (TaskHandle taskHandle, int32 sampleMode, uInt64 sampsPerChan);
^
./NIDAQmx.h:2656:102: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxCfgBurstHandshakingTimingImportClock(TaskHandle taskHandle, int32 sampleMode, uInt64 sampsPerChan, float64 sampleClkRate, const char sampleClkSrc[], int32 sampleClkActiveEdge, int32 pauseWhen, int32 readyEventActiveLevel);
^
./NIDAQmx.h:2658:102: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxCfgBurstHandshakingTimingExportClock(TaskHandle taskHandle, int32 sampleMode, uInt64 sampsPerChan, float64 sampleClkRate, const char sampleClkOutpTerm[], int32 sampleClkPulsePolarity, int32 pauseWhen, int32 readyEventActiveLevel);
^
./NIDAQmx.h:2659:151: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxCfgChangeDetectionTiming (TaskHandle taskHandle, const char risingEdgeChan[], const char fallingEdgeChan[], int32 sampleMode, uInt64 sampsPerChan);
^
./NIDAQmx.h:2661:92: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxCfgImplicitTiming (TaskHandle taskHandle, int32 sampleMode, uInt64 sampsPerChan);
^
./NIDAQmx.h:2663:145: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxCfgPipelinedSampClkTiming (TaskHandle taskHandle, const char source[], float64 rate, int32 activeEdge, int32 sampleMode, uInt64 sampsPerChan);
^
./NIDAQmx.h:6228:66: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxGetLoggingSampsPerFile(TaskHandle taskHandle, uInt64 *data);
^
./NIDAQmx.h:6229:66: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxSetLoggingSampsPerFile(TaskHandle taskHandle, uInt64 data);
^
./NIDAQmx.h:6236:75: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxGetLoggingFilePreallocationSize(TaskHandle taskHandle, uInt64 *data);
^
./NIDAQmx.h:6237:75: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxSetLoggingFilePreallocationSize(TaskHandle taskHandle, uInt64 data);
^
./NIDAQmx.h:6240:62: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxGetReadCurrReadPos(TaskHandle taskHandle, uInt64 *data);
^
./NIDAQmx.h:6244:75: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxGetReadTotalSampPerChanAcquired(TaskHandle taskHandle, uInt64 *data);
^
./NIDAQmx.h:6485:67: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxGetSampQuantSampPerChan(TaskHandle taskHandle, uInt64 *data);
^
./NIDAQmx.h:6486:67: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxSetSampQuantSampPerChan(TaskHandle taskHandle, uInt64 data);
^
./NIDAQmx.h:7297:64: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxGetWriteCurrWritePos(TaskHandle taskHandle, uInt64 *data);
^
./NIDAQmx.h:7325:77: error: unknown type name 'uInt64'
int32 __CFUNC DAQmxGetWriteTotalSampPerChanGenerated(TaskHandle taskHandle, uInt64 *data);
@5k3105 these are 100% C-related problems, I mean they arise because your C compiler can't compile the header given the defines you have during the compilation. I think you have to define something, there is two options:
1) Run go install
this way: CGO_CFLAGS="-D__linux__=1" go install
2) Add platform-specific FlagGroups to cgogen config (see https://github.com/xlab/cgogen/wiki/Generator-config-section#flaggroups)
@5k3105 There are some bad news by the way. There is a lot, A LOT of methods that use ...
variadic argument lists that are not supported in CGO. Normally there is two options to handle them: 1) ignore, 2) write a wrapper. Given their count, 2) is out of question, and 1) is probably too.
So for now, the quickest way to deal with it is to ignore:
- {action: ignore, from: "^DAQmxGet"}
- {action: ignore, from: "^DAQmxCreate"}
- {action: ignore, from: "^DAQmxSet"}
You may add rules explicitly for variadic methods only, this should help you to get things working at least for anything else.
Note that ...
variadics are not supported, but wrapper auto-generation can be done, this is scheduled on January holidays I guess. You can track progress in https://github.com/xlab/cgogen/issues/9
C:\goworksp\src\local\telem
λ set CGO_CFLAGS="-D__linux__=1"
C:\goworksp\src\local\telem
λ go install
# local/NIDAQmx
gcc: error: "-D__linux__=1": Invalid argument
C:\goworksp\src\local\telem
λ set CGO_CFLAGS="-D__linux__"
C:\goworksp\src\local\telem
λ go install
# local/NIDAQmx
gcc: error: "-D__linux__": Invalid argument
These are the only calls I will use right now:
nidaqmx.SelfTestDevice() // int32 __CFUNC DAQmxSelfTestDevice (const char deviceName[]);
nidaqmx.CreateTask() // int32 __CFUNC DAQmxCreateTask (const char taskName[], TaskHandle *taskHandle);
nidaqmx.CreateAIThrmcplChan() // int32 __CFUNC DAQmxCreateAIThrmcplChan (TaskHandle taskHandle, const char physicalChannel[], const char nameToAssignToChannel[], float64 minVal, float64 maxVal, int32 units, int32 thermocoupleType, int32 cjcSource, float64 cjcVal, const char cjcChannel[]);
nidaqmx.ValDegC
nidaqmx.ValTTypeTC
nidaqmx.ValBuiltIn
nidaqmx.ValGroupByScanNumber
nidaqmx.StartTask() // int32 __CFUNC DAQmxStartTask (TaskHandle taskHandle);
nidaqmx.ReadAnalogF64() // int32 __CFUNC DAQmxReadAnalogF64 (TaskHandle taskHandle, int32 numSampsPerChan, float64 timeout, bool32 fillMode, float64 readArray[], uInt32 arraySizeInSamps, int32 *sampsPerChanRead, bool32 *reserved);
nidaqmx.StopTask() // int32 __CFUNC DAQmxStopTask (TaskHandle taskHandle);
nidaqmx.ClearTask() // int32 __CFUNC DAQmxClearTask (TaskHandle taskHandle);
Ok, I think the env var took.
Using:
GENERATOR:
PackageName: nidaqmx
PackageDescription: "Package nidaqmx provides Go bindings for National Instruments NIDAQmx"
PackageLicense: "THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS."
Includes: ["NIDAQmx.h"]
PARSER:
SourcesPaths: ["NIDAQmx.h"]
Defines:
__linux__: 1
TRANSLATOR:
ConstRules:
defines: expand
Rules:
global:
- {action: ignore, from: "^DAQmxGet"}
- {action: ignore, from: "^DAQmxCreate"}
- {action: ignore, from: "^DAQmxSet"}
- {action: accept, from: "^DAQmx"}
- {action: replace, from: "^DAQmx"}
- {transform: export}
post-global:
- {action: replace, from: _$}
- {load: snakecase}
Lots of lines like this:
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x1673d): undefined reference to `DAQmxStartNewFile'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16793): undefined reference to `DAQmxStartTask'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x167e9): undefined reference to `DAQmxStopTask'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16846): undefined reference to `DAQmxSwitchCloseRelays'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x168ae): undefined reference to `DAQmxSwitchConnect'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x1690b): undefined reference to `DAQmxSwitchConnectMulti'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16969): undefined reference to `DAQmxSwitchCreateScanList'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x169d1): undefined reference to `DAQmxSwitchDisconnect'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16a2e): undefined reference to `DAQmxSwitchDisconnectAll'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16a8b): undefined reference to `DAQmxSwitchDisconnectMulti'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16b06): undefined reference to `DAQmxSwitchFindPath'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16b79): undefined reference to `DAQmxSwitchGetMultiRelayCount'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16bec): undefined reference to `DAQmxSwitchGetMultiRelayPos'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16c4a): undefined reference to `DAQmxSwitchGetSingleRelayCount'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16ca8): undefined reference to `DAQmxSwitchGetSingleRelayPos'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16d05): undefined reference to `DAQmxSwitchOpenRelays'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16d63): undefined reference to `DAQmxSwitchSetTopologyAndReset'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16db9): undefined reference to `DAQmxSwitchWaitForSettling'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16e16): undefined reference to `DAQmxTaskControl'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16e6c): undefined reference to `DAQmxTristateOutputTerm'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16ec2): undefined reference to `DAQmxUnreserveNetworkDevice'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16f30): undefined reference to `DAQmxWaitForNextSampleClock'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x16f93): undefined reference to `DAQmxWaitUntilTaskDone'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x1703a): undefined reference to `DAQmxWriteAnalogF64'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x170be): undefined reference to `DAQmxWriteAnalogScalarF64'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17165): undefined reference to `DAQmxWriteBinaryI16'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x1720c): undefined reference to `DAQmxWriteBinaryI32'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x172b3): undefined reference to `DAQmxWriteBinaryU16'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x1735a): undefined reference to `DAQmxWriteBinaryU32'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17413): undefined reference to `DAQmxWriteCtrFreq'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x174a7): undefined reference to `DAQmxWriteCtrFreqScalar'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17560): undefined reference to `DAQmxWriteCtrTicks'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x175eb): undefined reference to `DAQmxWriteCtrTicksScalar'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x176a4): undefined reference to `DAQmxWriteCtrTime'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17738): undefined reference to `DAQmxWriteCtrTimeScalar'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x177df): undefined reference to `DAQmxWriteDigitalLines'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17861): undefined reference to `DAQmxWriteDigitalScalarU32'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17908): undefined reference to `DAQmxWriteDigitalU16'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x179af): undefined reference to `DAQmxWriteDigitalU32'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17a56): undefined reference to `DAQmxWriteDigitalU8'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17af2): undefined reference to `DAQmxWriteRaw'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17b65): undefined reference to `DAQmxWriteToTEDSFromArray'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17bcd): undefined reference to `DAQmxWriteToTEDSFromFile'
C:\Users\clott\AppData\Local\Temp\go-build291329218\local\NIDAQmx\_obj\nidaqmx.cgo2.o:nidaqmx.cgo2.c:(.text+0x17c2e): undefined reference to `DAQmxXSeriesCalAdjust'
collect2.exe: error: ld returned 1 exit status
@5k3105 Yeah, sure, you should link against a library. You're pretty close. Depending on the environment, you must link against .dll, .so or .dylib
If you library is located under name libnidaqmx.so
in /usr/local/lib
then specify CGO_LDFLAGS="-L/usr/local/lib -lnidaqmx"
I hope you see the pattern in these.
Another option is to fill the FlagGroups
in generator's config that will specify LDFLAGS
for your platform, there are many other options but they're much more advanced (and time consuming).
TIP! If you have pkg-config
installed, you can take advantage of that, see example:
https://github.com/xlab/vorbis-go/blob/master/vorbis.yml#L6
UPD: oops, you're under Windows, so just locate the library on your disk and paste the path of directory to -L
flag and the mingw64 compatible lib name to -l
.
@xlab Thank you for all your help!
λ go install
# local/NIDAQmx
..\NIDAQmx\const.go:2067: ReadWaitMode redeclared in this block
previous declaration at ..\NIDAQmx\const.go:1519
..\NIDAQmx\const.go:2441: ValPulseTime redeclared in this block
previous declaration at ..\NIDAQmx\const.go:2417
..\NIDAQmx\const.go:2445: ValPulseTicks redeclared in this block
previous declaration at ..\NIDAQmx\const.go:2419
I was initially going to just delete these extra lines but it turns out they are indeed redeclared but with different values sometimes. So I just put a '2' behind the second instances of these and it stopped complaining.
My CGO_LDFLAGS looks like this: -L/goworksp/src/local/NIDAQmx -lnicaiu
But I get:
λ go install
# local/telem
C:\Go\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1
C:/TDM-GCC-64/bin/../lib/gcc/x86_64-w64-mingw32/5.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lnicaiu
collect2.exe: error: ld returned 1 exit status
I feel like I've tried every permutation of the above. It's a .dll file - "nicaiu.dll" (from the Windows/Wow64 folder on the target machine) I copied and placed in the nidaqmx folder. I found an old post refering to this:
and
http://forums.ni.com/t5/Multifunction-DAQ/Howto-use-NIDAQmx-with-mingw-gcc-3-4-2/td-p/294361
Funny thing is, even when I remove the '-lnicaiu' from the flags:
CGO_LDFLAGS =-L/goworksp/src/local/NIDAQmx
It still responds with cannot find -lnicaiu
:
λ go install
# local/telem
C:\Go\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1
C:/TDM-GCC-64/bin/../lib/gcc/x86_64-w64-mingw32/5.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lnicaiu
collect2.exe: error: ld returned 1 exit status
That's strange indeed, ld must always be capable of finding nicaiu.dll
in paths defined by -L
.
:(
In the second link it mentioned:
Qt 4.7 with included mingw can use NIDAQmx.lib "as is" with LIBS += "
\NIDAQmx.lib" statement in pro file.
Not sure what this means but I gave qt a try:
λ go install
# local/telem
C:\Go\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1
C:/Qt/Qt5.7.0/Tools/mingw530_32/bin/../lib/gcc/i686-w64-mingw32/5.3.0/../../../../i686-w64-mingw32/bin/ld.exe: unrecognised emulation mode: i386pep
Supported emulations: i386pe
collect2.exe: error: ld returned 1 exit status
You're going too deeply in the rabbit hole. I think it's pretty solvable with plain MinGW64 + msys shell, with clean env variables. Just clean the mess.
Hi,
Got it to compile! (complete go build log at bottom)
host link: "gcc" "-m64" "-gdwarf-2" "-mconsole" "-o" "C:\\msys64\\tmp\\go-build984789194\\local\\telem\\_obj\\exe\\a.out.exe" "C:\\msys64\\tmp\\go-link-612005067\\go.o" "C:\\msys64\\tmp\\go-link-612005067\\000000.o" "C:\\msys64\\tmp\\go-link-612005067\\000001.o" "-L\\\\goworksp\\\\src\\\\local\\\\NIDAQmx" "-lnicaiu" "-g" "-O2" "-lmsvcrt" "-lm" "-mthreads" "-lwinmm" "-lws2_32" "-lntdll" "-ladvapi32" "-lkernel32"
Meaningful line:
"-L\\\\goworksp\\\\src\\\\local\\\\NIDAQmx"
Which I could not get to change through any of my env vars (.profile, .bash_profile, windows env vars). It should be /c/goworksp/src/local/NIDAQmx
. Since it was missing the c, it couldn't find the .dll. Wound up putting dll in /c/usr/local/lib
and it compiled.
So :) thank you!
I now have two problems. The SelfTestDevice which takes a string and returns an int (error code) is coming back with 'Device identifier is invalid.' Pretty sure this is the correct string I am sending it since I am just translating some python over - so same device name. Is there any way that string (const char deviceName[]) could get changed?
I am wondering if the way I changed the constants may be disturbing things (https://github.com/xlab/cgogen/issues/11#issuecomment-262314019). I just did a search and replace on the names but any of the functions using the old names will surely take the first value and not the second value I renamed to 'value2'.
Second - nidaqmx.CreateTask() // int32 __CFUNC DAQmxCreateTask (const char taskName[], TaskHandle *taskHandle);
This is the first function used in the code. It does not have a variadic argument but is also not generated because it starts with 'Create'. So there is a way I can include that single function? (- {action: accept, from: "^DAQmxCreateTask"}
):
Rules:
global:
- {action: accept, from: "^DAQmxCreateTask"}
- {action: ignore, from: "^DAQmxGet"}
- {action: ignore, from: "^DAQmxCreate"}
- {action: ignore, from: "^DAQmxSet"}
- {action: accept, from: "^DAQmx"}
- {action: replace, from: "^DAQmx"}
- {transform: export}
go build log:
clott@N-04711 MINGW64 /c/goworksp/src/local/telem
$ go build -v -x -ldflags "-L /c/goworksp/src/local/NIDAQmx -v"
WORK=C:\msys64\tmp\go-build984789194
local/telem
mkdir -p $WORK\local\telem\_obj\
mkdir -p $WORK\local\telem\_obj\exe\
cd C:\goworksp\src\local\telem
"C:\\Go\\pkg\\tool\\windows_amd64\\compile.exe" -o "C:\\msys64\\tmp\\go-build984789194\\local\\telem.a" -trimpath "C:\\msys64\\tmp\\go-build984789194" -p main -complete -buildid 6c79789db6d79a20215dc936c2f622a43fbe87f4 -D _/C_/goworksp/src/local/telem -I "C:\\msys64\\tmp\\go-build984789194" -I "C:\\goworksp\\pkg\\windows_amd64" -pack "C:\\goworksp\\src\\local\\telem\\main.go"
cd .
"C:\\Go\\pkg\\tool\\windows_amd64\\link.exe" -o "C:\\msys64\\tmp\\go-build984789194\\local\\telem\\_obj\\exe\\a.out.exe" -L "C:\\msys64\\tmp\\go-build984789194" -L "C:\\goworksp\\pkg\\windows_amd64" -extld=gcc -buildmode=exe -buildid=6c79789db6d79a20215dc936c2f622a43fbe87f4 -L /c/goworksp/src/local/NIDAQmx -v "C:\\msys64\\tmp\\go-build984789194\\local\\telem.a"
# local/telem
HEADER = -H10 -T0x401000 -D0x0 -R0x1000
searching for runtime.a in $WORK\runtime.a
searching for runtime.a in C:\goworksp\pkg\windows_amd64\runtime.a
searching for runtime.a in \c\goworksp\src\local\NIDAQmx\runtime.a
searching for runtime.a in C:\Go\pkg\windows_amd64\runtime.a
0.00 deadcode
0.02 pclntab=285276 bytes, funcdata total 44156 bytes
0.02 dodata
0.02 reloc
0.03 reloc
0.03 asmb
0.03 codeblk
0.04 datblk
0.04 sym
0.04 dwarf
0.04 headr
0.04 symsize = 0
host link: "gcc" "-m64" "-gdwarf-2" "-mconsole" "-o" "C:\\msys64\\tmp\\go-build984789194\\local\\telem\\_obj\\exe\\a.out.exe" "C:\\msys64\\tmp\\go-link-612005067\\go.o" "C:\\msys64\\tmp\\go-link-612005067\\000000.o" "C:\\msys64\\tmp\\go-link-612005067\\000001.o" "-L\\\\goworksp\\\\src\\\\local\\\\NIDAQmx" "-lnicaiu" "-g" "-O2" "-lmsvcrt" "-lm" "-mthreads" "-lwinmm" "-lws2_32" "-lntdll" "-ladvapi32" "-lkernel32"
C:\Go\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1
C:/TDM-GCC-64/bin/../lib/gcc/x86_64-w64-mingw32/5.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lnicaiu
collect2.exe: error: ld returned 1 exit status
Regarding strings: you need to form an 0-ending string like "hello\x00"
otherwise you hand a full memory chunk to C land, and it reads your passwords from a browser tab here too.
Take these snippets:
var end = "\x00"
var endChar byte = '\x00'
func safeString(s string) string {
if len(s) == 0 {
return end
}
if s[len(s)-1] != endChar {
return s + end
}
return s
}
func safeStrings(list []string) []string {
for i := range list {
list[i] = safeString(list[i])
}
return list
}
@5k3105 About the ignore case:
- {action: ignore, from: "^DAQmxCreate[^T]+"}
You can use regexp to just ignore functions that are not DAQmxCreateT*
(I checked, there is no ...
in DAQmxCreateT*
functions).
I probably need to add respect of the filters order, so you could override "^DAQmxCreate"
with "^DAQmxCreateTask"
by placing it below, but it's technically harder than 1 hour so I postpone that change. To be specific, this particular function needs to learn how to respect the order of rules https://github.com/xlab/cgogen/blob/master/translator/translator.go#L912-L926 but currently it operates on separate maps and can't tell if accept
rules are below ignore
rules in the config.
Glad you got that working. Be careful with strings.
Hi,
I don't understand why TaskHandle passed into DAQmxCreateTask as *taskHandle is represented in go as []unsafe.Pointer.
This is my code:
var th unsafe.Pointer
nidaqmx.CreateTask("task1", &th)
nidaqmx.CreateAIThrmcplChan(th, safeString(DAQMX_DEVICE_NAME + "/ai1"), safeString("T0 - LiDAR box right side"), -60.0, 100.0, nidaqmx.ValDegC, nidaqmx.ValTTypeTC, nidaqmx.ValBuiltIn, 25.0, safeString(" "))
TaskHandle (https://github.com/5k3105/NIDAQmx/blob/master/NIDAQmx.h#L99):
typedef void* TaskHandle;
CreateTask (https://github.com/5k3105/NIDAQmx/blob/master/NIDAQmx.h#L2510):
int32 __CFUNC DAQmxCreateTask (const char taskName[], TaskHandle *taskHandle);
CreateAIThrmcplChan:
int32 __CFUNC DAQmxCreateAIThrmcplChan (TaskHandle taskHandle, const char physicalChannel[], const char nameToAssignToChannel[], float64 minVal, float64 maxVal, int32 units, int32 thermocoupleType, int32 cjcSource, float64 cjcVal, const char cjcChannel[]);
generated go:
// CreateTask function as declared in nidaqmx\NIDAQmx.h:2510
func CreateTask(TaskName string, TaskHandle []unsafe.Pointer) int32 {
cTaskName, _ := unpackPCharString(TaskName)
cTaskHandle, _ := (*unsafe.Pointer)(unsafe.Pointer((*sliceHeader)(unsafe.Pointer(&TaskHandle)).Data)), cgoAllocsUnknown
__ret := C.DAQmxCreateTask(cTaskName, cTaskHandle)
__v := (int32)(__ret)
return __v
}
// CreateAIThrmcplChan function as declared in nidaqmx\NIDAQmx.h:2547
func CreateAIThrmcplChan(TaskHandle unsafe.Pointer, PhysicalChannel string, NameToAssignToChannel string, MinVal float64, MaxVal float64, Units int32, ThermocoupleType int32, CjcSource int32, CjcVal float64, CjcChannel string) int32 {
cTaskHandle, _ := (unsafe.Pointer)(TaskHandle), cgoAllocsUnknown
cPhysicalChannel, _ := unpackPCharString(PhysicalChannel)
cNameToAssignToChannel, _ := unpackPCharString(NameToAssignToChannel)
cMinVal, _ := (C.float64)(MinVal), cgoAllocsUnknown
cMaxVal, _ := (C.float64)(MaxVal), cgoAllocsUnknown
cUnits, _ := (C.int32)(Units), cgoAllocsUnknown
cThermocoupleType, _ := (C.int32)(ThermocoupleType), cgoAllocsUnknown
cCjcSource, _ := (C.int32)(CjcSource), cgoAllocsUnknown
cCjcVal, _ := (C.float64)(CjcVal), cgoAllocsUnknown
cCjcChannel, _ := unpackPCharString(CjcChannel)
__ret := C.DAQmxCreateAIThrmcplChan(cTaskHandle, cPhysicalChannel, cNameToAssignToChannel, cMinVal, cMaxVal, cUnits, cThermocoupleType, cCjcSource, cCjcVal, cCjcChannel)
__v := (int32)(__ret)
return __v
}
@5k3105 That's because in C there is no difference between an array and a pointer without some context (like length), this is indistinguishable by translator.
So cgogen assumes by default that every function argument or struct field being a pointer means it's a slice (and that's correct). And return values are assumed to be pointers (just more likely return a pointer rather than an array, due to unknown length). But there is a legitimate way to change this because of convenience of pointer types (as opposed to slices).
Please check out the docs about this behaviour and how to deal with it using PtrTips: https://github.com/xlab/cgogen/wiki/Translator-config-section#ptrtips
thus you can override the default behaviour for all by providing a line that covers everything. And work out the cases when you actually have slices, not pointers. Or maybe make a rule making every first argument of any function be always a pointer, useful for receivers. By the way, you can find a plenty of legit examples here: https://github.com/xlab/cgogen/wiki/Examples
For particular example, a typical PtrTip section: https://github.com/xlab/android-go/blob/master/gles2.yml#L26-L39
Ok, I will take a look at that.
I will do this temporarily then:
var ths []unsafe.Pointer
nidaqmx.CreateTask("task1", ths)
th := ths[0]
nidaqmx.CreateAIThrmcplChan(th, safeString(DAQMX_DEVICE_NAME + "/ai1"), safeString("T0 - LiDAR box right side"), -60.0, 100.0, nidaqmx.ValDegC, nidaqmx.ValTTypeTC, nidaqmx.ValBuiltIn, 25.0, safeString(" "))
and I will test:
PtrTips:
function:
- {target: ^DAQmxCreateTask$, tips: [0,ref]}
@5k3105
nidaqmx.CreateTask("task1", ths)
you forgot safeString
or \x00
in string.
Thank you ;)
Hi,
I went ahead and updated the yml and generated the lib again, but instead of giving
TaskHandle *unsafe.Pointer
in CreateTask, it gave TaskHandle unsafe.Pointer
So I changed it in the file to *unsafe.Pointer
(which is probably wrong, right?).
It did compile but I get nothing in response to ReadAnalogF64 so I imagine this is wrong?
Later I ran into:
func ReadAnalogF64(TaskHandle unsafe.Pointer, NumSampsPerChan int32, Timeout float64, FillMode uint32, ReadArray []float64, ArraySizeInSamps uint32, SampsPerChanRead []int32, Reserved []uint32) int32 {
SampsPerChanRead needed to be *int32
so I updated the yml:
PtrTips:
function:
- {target: ^DAQmxCreateTask$, tips: [0,ref]}
- {target: ^DAQmxReadAnalogF64$, tips: [0, 0, 0, 0, 0, 0, ref, ref]}
Another point that might be making things misbehave:
For ReadAnalogF64, parameter ReadArray size is dependent on the following parameter called ArraySizeInSamps.
Since ReadArray expects a slice in Go, I can't:
var readarray [16]float64
when ArraySizeInSamps = 16
In the other code I look at the array size is statically defined before it's use:
data = numpy.zeros((1000,), dtype=numpy.float64)
DAQmxReadAnalogF64(taskHandle,1000,10.0,DAQmx_Val_GroupByChannel,data,1000,byref(read),None)
or in C:
float64 data[1000];
DAQmxReadAnalogF64(taskHandle,1000,10.0,DAQmx_Val_GroupByChannel,data,1000,&read,NULL)
(examples from: https://pythonhosted.org/PyDAQmx/usage.html)
Hi,
I also get
Error -200492 Reserved parameter must be NULL.
for the last parameter of DAQmxReadAnalogF64. I have tried to put nil there and also
var reserved uint32
reserved = 0
f64 := nidaqmx.ReadAnalogF64(th, 1, 100.0, nidaqmx.ValGroupByScanNumber, readarray, 16, &samplesperchanread, &reserved)
which gives me the error as well.
How do I specify a C NULL in Go when it expects a *uint32 ?
How do I specify a C NULL
As usual really, nil
. Instead:
, &reserved)
do:
, nil)
Hi. Thank you for your help.
original error code was:
Error -200492 Reserved parameter must be NULL.
after the change to nil
for 'reserved' parameter, error code is:
Error -200230 NULL pointer was passed for a required parameter.
I think this now refers to the 'readarray' parameter.
(TaskHandle taskHandle, int32 numSampsPerChan, float64 timeout, bool32 fillMode, float64 readArray[], uInt32 arraySizeInSamps, int32 *sampsPerChanRead, bool32 *reserved)
Hi,
Do you know of any way I can fix this:
..\NidaqMonitor\nidaqMonitor.go:57: cannot use readarray (type [16]float64) as type []float64 in argument to nidaqmx.ReadAnalogF64
Use arr = make([]float64, 16)
instead of [16]float64
. That seems to be a Go error.
By the way, as the issue is resolved, I propose to move the discussion to email (max@kc.vc)
Hi,
I am not very experienced with C. I was wondering if you could give me some instruction on what I am doing wrong please?
My repo is: https://github.com/5k3105/NIDAQmx
error:
processing nidaqmx.yml ⠸[ERR] NIDAQmx.h:85:29: unexpected identifier int64, expected one of ['(', ')', ',', ':', ';', '=', '[', '{', _Bool, _Complex, _Noreturn, _Static_assert, asm, auto, char, const, double, enum, extern, float, inline, int, long, register, restrict, short, signed, static, struct, typedef, typedefname, typeof, union, unsigned, void, volatile]
Thanks