I want to create a dll from nim code.
But i failed to register some other exports than "NimMainInner".
Even if i try this simple example its not working:
proc Hellow(): cint {.exportc.} =
echo("hello")
return 1
i've compiled it with nim c --app:lib libh4x.nim
and nim c -d:release --app:lib --no_main libh4x.nim
i use Nim Compiler Version 0.11.2 (2015-05-04) [Windows: i386]
to inspect the dll i use dllexp.exe.
I've also tried to load the dll with python ctypes, but none of my exports are shown or are callable. I can see the proc name in the resulting dll with an hexeditor, though.
What have i missed here?
The dynlib pragma was missing. So i changed the definition to:
proc Hellow(): cint {.exportc,dynlib.} =
echo("hello")
result = 1
now it works.
Note: If you use this with pythons ctypes and with function parameters make sure to use ctypes.cdll.LoadLibrary instead of ctypes.windll.LoadLibrary:
Python ctypes argument errors
and to declare the function like this:
proc myinit(procid : int) {.cdecl,exportc,dynlib.} =
discard
Related
I'm using the FFI to work with a portable C library. However, I'm running into issues when trying to use some of the library functions that use fopen internally, probably due to filename encoding.
GHC offers some mechanisms that can be used to control the encoding used with functions like pushCString. E.g., the following code should push a Haskell String value as nul-terminated C string using the encoding used by the file system:
import qualified GHC.Foreign as GHC
import qualified GHC.IO.Encoding as GHC
main =
encoding <- GHC.getFileSystemEncoding
GHC.pushCString encoding "my example"
This appears to work well on Unix-like systems, but not on Windows: My program cannot find files that contain umlauts.
The documentation of getFileSystemEncoding comes with the warning that hints at the problem.
On Windows, this encoding should not be used if possible because the use of code pages is deprecated: Strings should be retrieved via the "wide" W-family of UTF-16 APIs instead
But this gives no info on how to deal with a filepath that will be passed to a foreign function.
Minimal example
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C (CString)
import Foreign.Ptr (Ptr, nullPtr)
import qualified GHC.Foreign as GHC
import qualified GHC.IO.Encoding as GHC
filename = "Ümlauts.txt"
main = do
writeFile filename "content" -- ensure file exists
fsEncoding <- GHC.getFileSystemEncoding
GHC.withCString fsEncoding filename $ \fscpath -> do
handle <- greeting_fopen fscpath
if handle == nullPtr
then error $ "Could not open file " ++ filename
else do
putStrLn "file opened successfully"
-- Library function that uses fopen internally
foreign import ccall "greeting.c greeting_fopen"
greeting_fopen :: CString -> IO (Ptr ())
where greeting.c contains
#include <stdio.h>
#include <stdlib.h>
FILE *greeting_fopen (const char *filename) {
printf("Hello, now trying to open %s\n", filename);
return fopen (filename, "r");
}
Running ghc --make greeting.c main.hs and executing the resulting binary succeeds on Linux, but fails on Windows due to the file not being found.
Is there a way to make this work?
The Windows documentation for fopen states:
The fopen function opens the file that is specified by filename. By default, a narrow filename string is interpreted using the ANSI codepage (CP_ACP).
Therefore, that's the code page that must be used to encode the filename when it is passed to the library function. We can't pass CPACP (or CP_ACP) as the argument for System.IO.mkTextEncoding, as that function only supports numerical code pages like "CP1252".
However, CP_ACP is available as code page 0, so we can use
fsEncoding <- System.IO.mkTextEncoding "CP0"
Of course, this won't work with Linux, so we need some ugly CPP code like
#if defined(mingw32_HOST_OS)
fsEncoding <- mkTextEncoding "CP0"
#else
fsEncoding <- getFileSystemEncoding
#endif
The code may still fail if the filename cannot be represented in the ANSI codepage, but that seems to be an unfixable limitation.
The use of "CP0" is a bit of a hack; for completeness, here's some code that uses getACP from the Windows API to get the right codepage.
import Data.Word (Word32 (..))
import GHC.IO.Encoding.CodePage (codePageEncoding)
foreign import ccall unsafe "windows.h GetACP"
getACP :: IO Word32
getFileSystemEncoding =
codePageEncoding <$> getACP
In IDL console I want another way in order to obtain variable value, for debug purpose. This is how I do now:
IDL> cvel=299.792458e6
IDL> print, cvel
2.99792e+008
There is a easy and quick way to obtain cvel value in console? Like for example in the following (erroneous) command:
IDL> cvel
% Attempt to call undefined procedure/function: 'CVEL'.
This was added to IDL recently (at least by IDL 8.5, maybe earlier):
IDL> cvel=299.792458e6
IDL> cvel
2.9979245e+08
I have recently started studying parallel processing in Julia and I am having an issue which I don't really understand how to fix.
After having executed Julia with julia -p 4 I want to load the Distributions module in all the processes and I would like to define a Type which depends on Distributions.
The following apparently works correctly when I include it:
#everywhere using Distributions
type TypeDistrib{T <: Float64}
d::Distributions.Normal{T}
end
If I write exactly the same code as a module, then it doesn't:
module test
#everywhere using Distributions
type TypeDistrib{T <: Float64}
d::Distributions.Normal{T}
end
export TypeDistrib
end
The above gives the following error message:
ERROR: LoadError: UndefVarError: Distributions not defined
in include_from_node1(::String) at ./loading.jl:488
in include_from_node1(::String) at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
while loading /***/test.jl, in expression starting on line 4
Would you please clarify what I am not doing correctly here?
Note: I replaced the full path in the error message with *** since it was confusing.
#everywhere something evaluates something in the Main module across all processes. And in this case, not in test module, and therefore the error in the second case and not in the first.
Perhaps
#everywhere module test
using Distributions
type TypeDistrib{T <: Float64}
d::Distributions.Normal{T}
end
export TypeDistrib
end
does what is meant.
In the Julia NMF package a verbose option provides information on convergence using the #printf macro.
How can I access this output without rewriting the NMF package io?
To rephrase, having a function f() containing the macro #printf, how can I access the output outside f()?
This does seem like useful functionality to have: I would suggest that you file an issue with the package.
However, as a quick hack, something like the following should work:
oldout = STDOUT
(rd,wr) = redirect_stdout()
start_reading(rd)
# call your function here
flush_cstdio()
redirect_stdout(oldout)
close(wr)
s = readall(rd)
close(rd)
s
I am writing a code in Fortran to read a list of properties from a file, and am using the IOSTAT function to skip invalid data. The relevant section of code is as follows:
do j=1,1000
read(22,*,IOSTAT=ios) step,T,K,U,Tot,P
If(IS_IOSTAT_END(ios)) Exit !exits loop if value is not number or end of file
IF(ios.ne.0) cycle
sumT=sumT+T
sumU=sumU+U
sumK = sumK + K
sumKsq = sumKsq + (K**2.d0)
end if
end do
This code has previously worked fine when running on Linux, but when running on Mac OSX I get the error message 'IS_IOSTAT_END has no implicit type'. Could somebody please explain how to correct this?
Thanks
The intrinsic procedure IS_IOSTAT_END(i) is defined since Fortran 2003. Sufficiently recent compiler version must be used.