n0bra1n3r / cinterop

A C/C++ interop library for the Nim programming language

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

result.m_type

mantielero opened this issue · comments

I am playing with OCCUtils. It depends on OpenCascade library.

I wrote the following example:

{.passL: "-loccutils".}
{.passC:"-I/usr/local/include/occutils -I/usr/include/opencascade" .}

import cinterop

# From: /usr/include/opencascade
type
  TopoDS_Shape* {.importcpp: "TopoDS_Shape", header: "TopoDS_Shape.hxx", bycopy.} = object of RootObj  
  TopoDS_Solid* {.importcpp: "TopoDS_Solid", header: "TopoDS_Solid.hxx", bycopy.} = object of TopoDS_Shape 

# From: /usr/local/include/occutils 
csource "Primitive.hxx":
  cnamespace OCCUtils:
    cnamespace Primitive:
      type primitive* {.cgen:"OCCUtils::Primitive::$1(@)".} = object of CClass  # OCCUtils::Primitive::$1(@)

proc makeCube*(size:float):TopoDS_Solid =
  cexpr[TopoDS_Solid]^primitive.MakeCube(size)

proc main() =
  var myCube:TopoDS_Solid = makeCube(5)

main()

Which gives me the following error:

error: ‘class TopoDS_Solid’ has no member named ‘m_type’
   89 |         result.m_type = (&NTI__iFNg5Zv78nzJlY9cUWwvWwg_);

The c++ created contains:

...
/* section: NIM_merge_PROCS */
N_LIB_PRIVATE N_NIMCALL(TopoDS_Solid, makeCube__0MVTOneNhGZEGBJK1P9cGWQ)(NF size) {
	TopoDS_Solid result;
	result.m_type = (&NTI__iFNg5Zv78nzJlY9cUWwvWwg_);   //<------ ERROR
	result = /*OCCUtils::Primitive::primitive*/OCCUtils::Primitive::MakeCube(size);
	return result;
}
...

As a side note, I have tried this {.cgen:"OCCUtils::Primitive::$1(@)".} and {.cgen:"$1(@)".}. In the second case, shouldn't ÒCCUtils and Primitive be added given the cnamescape? Or maybe cnamescape shouldn't be used if I am using cgen?

You don't really need the cnamespace for this case. For your issue, try doing:

proc makeCube*(size:float):TopoDS_Solid {.noinit.} =
  cexpr[TopoDS_Solid]^primitive.MakeCube(size)

The noinit tells Nim not to initialize the hidden result variable and just return it directly.

You might also want to avoid using RootObj with interop stuff, as I've seen it cause problems before. You can either use CClass or use the inheritable pragma instead.

Note that cinterop is not a replacement for header + importcpp; it is meant to work alongside those pragmas. The point of the library is so you don't have to declare C++ types and functions to use them directly in your code. If you're going to declare functions on your own, it's better to just use importcpp and header directly:

proc makeCube*(size:float):TopoDS_Solid {.header:"Primitive.hxx" importcpp:"OCCUtils::Primitive::$1(@)".}

I added this in the readme a couple days ago:

This project is not a replacement for hand-written wrappers or wrapper generators like c2nim. This library is useful for quickly prototyping new code that depend on large C/C++ libraries, and is carefully designed so code can progressively be migrated to use Nim's header and importcpp pragmas directly.

Thanks a lot. It worked.

I am aware that this is no replacement for importcpp, but it is helping me a lot to understand better what I need to do.