Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Nimble package for supporting and simplifying import of symbols from C into Nim

License

NotificationsYou must be signed in to change notification settings

fredrikhr/nim-importc-helpers

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This nimble package provides some helper functionality for doingforeign-function-interfacing (FFI) with C functions in the Nim programminglanguage.

Distinct Type Helpers

Even though Nim does have enum types, these are not always the best choicewhen passing values on to a native C API. Also, bitflags are regurlarly usedin C APIs, but in Nim we would rather use theset type for that purpose.

This nimble package provides helpers to bridge enums, semi-enums and bitflagsfrom C to Nim.

Enums as distinct Types

In many C APIs, especially those that are tied to the operating system, a groupof constants is not implemented as an enum type, but rather as a series of#define constants. Often this is done, to provide a clear definition of thebit length for a parameter, since the bit-length of an enum type in C can beambigious depending on the compiler, target platform and other factors.

Unfortunenately, this habit makes it harder to translate C headers to equivalentNim bindings.

TheimplementDistictEnum macro can be placed in front of a block that declaresvalues for a distinct type, and will automatically implement the equalityoperator, and if desired, stringify and parse procs.

Consider the following C code:

#defineCOLOUR_RED 1#defineCOLOUR_BLUE 2#defineCOLOUR_GREEN 3typedefintCOLOUR,*PCOLOR;

Even though thisCOLOUR type can easily be implemented as an enum, there arecases when this is not possible or will cause complications.

Instead, let us implement the type above in Nim using a distinct type:

typeColour=distinctint32const  colour_red=1.Colour  colour_blue=2.Colour  colour_green=3.Colour

If we have a C API that returns aCOLOUR value, and we wanted to do somethingdepending on the value returned, we would now have to implement the==operator for the distinctColour type in Nim. Sure, the implementation istrivial, but it still has to be done, if we do not want to cast everyColourvalue to anint32 everytime we want to do something useful with it.

For that purpose, this package provides theimplementDistinctEnum macro.

typeColour=distinctint32implementDistinctEnum(Colour):const    colour_red=1.Colour    colour_blue=2.Colour    colour_green=3.Colour

Note that theconst block is now nested inside theimplementDistinctEnummacro invocation. The macro peeks into the const block and finds all identifierdefinitions in the block. The identifiers that are found are used by the macroas thelist of known values for theColour type. Then the macro generatesthe simple trivial implementations for these procs:

proc`==`*(a, b:Colour):bool= a.int32== b.int32proc`$`*(v:Colour):string=if v== colour_red:"colour_red"elif v== colour_blue:"colour_blue"elif v== colour_green:"colour_green"else:$(v.int32)procparseColour(s:string):ColourproctryParseColour(s:string, v:varColour):bool

Note that it uses thelist of known values for theColour type to implementthe stringify and parse procs. The parse procs use case-insensitiveunicode comparison with the identifiers of the known values.

Bitflags as distinct types

The Nim Manual states thatset types should be used when implementing flagtypes. However, theset type is not compatible with bitflags that areregurlarly used in C, andset types in Nim only support bitlength of up to16-bits.

With theimplementDistinctFlags macro, you can easily define a bitflags typeas a distinct numeric type, and the macro will provide all the procs you wouldexpect from a regular Nimset type.

Consider the following C example:

#defineBIT_0 (1 << 0)#defineBIT_1 (1 << 1)#defineBIT_2 (1 << 2)#defineBIT_3 (1 << 3)#defineBIT_4 (1 << 4)#defineBIT_5 (1 << 5)#defineBIT_6 (1 << 6)#defineBIT_7 (1 << 7)typedefintBITFLAGS8,*PBITFLAGS8;

The example above is shortened to only use 8 bits out the availble 32 bits.Look at the test case for this package, where all 32 bits are used.

In Nim with theimplementDistinctFlags macro:

typeBitflags8=distinctint32implementDistinctFlags(Bitflags8):const    bit_0= (1shl0).Bitflags8    bit_1= (1shl1).Bitflags8    bit_2= (1shl2).Bitflags8    bit_3= (1shl3).Bitflags8    bit_4= (1shl4).Bitflags8    bit_5= (1shl5).Bitflags8    bit_6= (1shl6).Bitflags8    bit_7= (1shl7).Bitflags8

The macro automatically provides the following procs:

proc`==`(a, b:Bitflags8):boolproc`and`(a, b:Bitflags8):Bitflags8proc`or`(a, b:Bitflags8):Bitflags8proc`not`(v:Bitflags8):Bitflags8proccontains(a, b:Bitflags8):boolproc`+`(a, b:Bitflags8):Bitflags8proc`*`(a, b:Bitflags8):Bitflags8proc`-`(a, b:Bitflags8):Bitflags8proc`<=`(a, b:Bitflags8):boolproc`<`(a, b:Bitflags8):boolprocincl(a:varBitflags8, b:Bitflags8):Bitflags8procexcl(a:varBitflags8, b:Bitflags8):Bitflags8proc`$`(v:Bitflags8):stringprocparseBitflags8(s:string):Bitflags8proctryParseBitflags8(s:string, v:varBitflags8):bool

The==,contains,+,*,-,<=,<,incl,excl procs providetheBitflags8 with all the procs that you would get ifBitflags8 was asettype.

Stringify for Bitflags returns a comma-separated list of all set flags in thespecified value, if there are bits set that have no known value associated withthem, the remainder is shown as its decimal representation.

doAssert (bit_0+ bit_4+ bit_6)=="{ bit_0, bit_4, bit_6 }"doAssert (bit_0+ bit_4+ (1shl8).Bitflags8)=="{ bit_0, bit_4, 256 }"

Extra information

For both theimplementDistinctEnum and theimplementDistinctFlags macros,there are overloads that accept a static bool argument, to indicate whether themacro should generate the stringify and parse procs. Since these methods carrythe string literals in the resulting code and thus also into the output binary,generating these string procs can significantly increase the output binary size.For example, the Windows SDK has several thousand lines of code where it definesHRESULT values that represent various error conditions. Producing a binarywith the names of all these constants inside it can easily increase the binarysize with approximately 7 MiB.

The AST block containing the known values for the distinct type that is passedin as the last argument for theimplementDistinctEnum and theimplementDistinctFlags macros can contain multipleconst sections. However,ALL identifiers declared in that blockMUST have the same type as theone specified for the macro.

Passinglet orvar sections instead ofconst sections for the known valuesto theimplementDistinctEnum and theimplementDistinctFlags macros ispossible, but not necessarily recommended.

About

Nimble package for supporting and simplifying import of symbols from C into Nim

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp