Thanks @Stefan_Salewski. I was to answer that all my types are public but I checked one last time before posting and I found that one type was not!
I still had compilation errors. For instance with **bar.nim** type Version* = object major: uint minor: uint build: uint revision: uint Run **foo.nim** import bar #include bar func getVers(major, minor, build, revision: ptr cuint) = ## Values provided by external API major[] = 1 minor[] = 1 build[] = 1 revision[] = 1 func getVersion*: Version {.inline.} = getVers( cast[ptr cuint](addr result.major), cast[ptr cuint](addr result.minor), cast[ptr cuint](addr result.build), cast[ptr cuint](addr result.revision) ) func `$`*(version: Version): string = ## Stringify the version under the usual pattern ## ``major.minor.build.revision`` result = $version.major & '.' & $version.minor & '.' & $version.build & '.' & $version.revision echo "Version=" & $getVersion() Run The error is `expression has no address; maybe use 'unsafeAddr'` on line `cast[ptr cuint](addr result.major),` in VisualStudio Code. But running `nim check foo`, I can see that there are previous errors and it is due to the fact that `Version` fields are not made public. Changing `Version` to the code below solved the problem and `import` can be used. **bar.nim** type Version* = object major*: uint minor*: uint build*: uint revision*: uint Run Now it becomes a different problem of information hiding. Do I want to have these fields visible by users? Are there problems using `import`? I suppose that if I import `bar.nim` in multiple files, I would get types redefinitions... I have to balance the advantages of both solutions.