How do I access environment variables in Vala? (as above) it seems simple, but I can't find how g_getenv() is mapped into Vala.
The answer lies in the bindings file. Vala uses bindings (in .vapi files) for binding its constructs to the C language. In this case you can grep through glib-2.0.vapi (on my system that is in /usr/share/vala-0.10/vapi), and you'll see that it is bound as:
unowned string? GLib.Environment.get_variable(string name)
It can be quite useful to have the location of the core VAPI files handy, because if you know the C name of a function you can just grep for it.
Related
I'd like to get a certain value from an environment variable in my Kotlin app, but I can't find anything about reading environment variables in the core libraries documentation.
I'd expect it to be under kotlin.system but there's really not that much there.
It is really easy to get a environment value if it exists or a default value by using the elvis operator in kotlin:
var envVar: String = System.getenv("varname") ?: "default_value"
You could always go down this approach:
val envVar : String? = System.getenv("varname")
Though, to be fair, this doesn't feel particularly idiomatic, as you're leveraging Java's System class, not Kotlin's.
And if you want to handle env var which do exists but is empty:
val myEnv = (System.getenv("MY_ENV") ?: "").ifEmpty { "default_value" }
(see edit history for previos versions)
You can use the kotlin extension Konfig
Konfig - A Type Safe Configuration API for Kotlin
Konfig provides an extensible, type-safe API for configuration properties gathered from multiple sources — built in resources, system properties, property files, environment variables, command-line arguments, etc.
For example: Key("http.port", intType)
While trying to prove to a colleague that it's possible to use C++ classes from F#, I came up with the following proof of concept. The first snippet is the code he provided for the challenge, and the code snippet below is my implementation in F#.
namespace testapp {
struct trivial_foo {
int bar;
__declspec(dllexport) void set(int n) { bar = n; }
__declspec(dllexport) int get() { return bar; }
}
}
open System.Runtime.InteropServices
type TrivialFoo =
struct
val bar: int
new(_bar: int) = { bar = _bar }
end
[<DllImport("Win32Project2.dll", EntryPoint="?get#trivial_foo#testapp##QAEHXZ", CallingConvention = CallingConvention.ThisCall)>]
extern int trivial_foo_get(TrivialFoo& trivial_foo)
[<DllImport("Win32Project2.dll", EntryPoint="?set#trivial_foo#testapp##QAEXH#Z", CallingConvention = CallingConvention.ThisCall)>]
extern void trivial_foo_set(TrivialFoo& trivial_foo, int bar)
type TrivialFoo with
member this.Get() = trivial_foo_get(&this)
member this.Set(bar) = trivial_foo_set(&this, bar)
When debugged in Visual Studio or run as a standalone program, this works predictably: TrivialFoo.Get returns the value of bar and TrivialFoo.Set assigns to it. When run from F# Interactive however, TrivialFoo.Set will not set the field. I suspect it might have something to do with accessing managed memory from unmanaged code, but that doesn't explain why it only happens when using F# Interactive. Does anyone know what's going on here?
I don't think this proof of concept is a good proof of interoperability. You may be better off creating DLL export definitions from your C++ project and use the de-decorated names instead.
As a PoC: F# creates MSIL that fits in the CLI, so it can interoperate with any other CLI language out there. If that is not enough and you want native-to-net interop, consider using COM, or as mentioned above, DLL export definitions on your C++. I personally wouldn't try to interop with C++ class definitions the way you suggest here, there are way easier ways to do that.
Alternatively, just change your C++ project into a .NET C++ project and you can access the classes directly from F#, while still having the power of C++.
Naturally, you may still be wondering why the example doesn't run in FSI. You can see a hint of an answer by running the following:
> System.IO.Directory.GetCurrentDirectory();;
val it : string = "R:\TMP"
To fix this, you have a myriad of options:
copy Win32Project2.dll to that directory
add whatever path it is in to PATH
use an absolute path
use a compile-time constant
or use an environment variable (the path will be expanded)
dynamically locate the dll and dynamically bind to it (complex)
Copying is probably the easiest of these solutions.
Since FSI is meant to be a REPL, it may not be best tailored for this kind of tasks that require multiple projects, libraries or otherwise complex configurations. You may consider voting on this FSI request for support for #package to import NuGet packages, which could be used to ease such tasks.
The counterpart of a C++ struct in F# is not necessarily a struct. In C++, the only difference between classes and structs resides in their default access restrictions.
In F#, structs are used for value types, classes are used for reference types. One problem with value types is that they are meant to be used as immutable values, and temporary copies are often created silently.
The problem you are observing is consistent with that scenario. For some reason, F# interactive creates a copy of your struct and passes a reference to that. The C++ code then modifies the copy, leaving the original untouched.
If you switch to using a class, make sure you pin the instance before letting native code use it, or you can end up in a situation where the garbage collector moves it after the native code gets a reference to it.
I think I saw somewhere a native function in Lua that can return a new userdata. Does it exist? Is it possible to create custom userdata from normal Lua script?
You may be thinking of newproxy
From: http://lua-users.org/wiki/HiddenFeatures
newproxy is an unsupported and undocumented function in the Lua base
library. From Lua code, the setmetatable function may only be used
on objects of table type. The newproxy function circumvents that
limitation by creating a zero-size userdata and setting either a new,
empty metatable on it or using the metatable of another newproxy
instance. We are then free to modify the metatable from Lua. This is
the only way to create a proxy object from Lua which honors certain
metamethods, such as __len.
It was also useful for __gc metamethods, as a hack to get a callback when the newproxy instance becomes free.
This feature was present in Lua 5.1, but removed in 5.2. In Lua 5.2, __gc metamethods can be set on zero sized tables, so the main impetus for newproxy went away.
Actually no, in pure Lua.
The type userdata is provided to allow arbitrary C data to be stored in Lua variables. … Userdata values cannot be created or modified in Lua, only through the C API. This guarantees the integrity of data owned by the host program.
link
If you embed luaVM in host C/C++ application, you can export some function to create userdata to Lua, but it's not a good practice. UD is designed to be a blackbox for Lua scripts.
SWIG considers C's enum as userdata. (I checked the source it generated. Perhaps a bug?). Then, I need to create userdata inside the Lua scripts itself... Any good ways?
Then, I need to create userdata inside the Lua scripts itself.
No. You want to create one of the enumerator values within Lua. You do that pretty much as you would in C: use the enumerator's name. This is an object that has the value of the enumerator. However SWIG's Lua component decides to marshal this is irrelevant; just use the name in your Lua code.
I have a name clashing problem while opening some .Net assemblies in my F# code using
open System.IO
The only option I found and use now is to provide the full names of types for conflicting types, but this is a little bit boring.
Is there any possibility to define an alias for .Net namespace in F# to prevent name clashing?
F# does not support aliasing of namespaces - only modules and types. So, to resolve the conflicts between .NET assemblies, you will, unfortunatelly, need to define aliases for all the types you're using.
This may be slightly easier thanks to the fact that F# type aliases are viewed as normal type declarations (by the F# compiler, not by the runtime). This means that, unlike with C# using keyword, you can define them in a spearate file:
// Aliases.fs
namespace SysIO
// Open the 'System' namespace to get a bit shorter syntax
// ('type File = File' is interpreted as discriminated union)
open System
type File = IO.File
type Directory = IO.Directory
In the rest of your application, you can now use SysIO.File. You still have to write the aliases, but at least you don't have to do that in every file...