Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

c++ ffi and RAII #3592

Open
vegansk opened this issue Nov 26, 2015 · 6 comments
Open

c++ ffi and RAII #3592

vegansk opened this issue Nov 26, 2015 · 6 comments
Labels
C++ Code Generation Invalid Code Acceptance Everything related to compiler not complaining about invalid code

Comments

@vegansk
Copy link
Contributor

vegansk commented Nov 26, 2015

Tried to make an example of c++ ffi and raii:

####################################################################################################
# RAII test for C++ FFI

{.passC: "-std=c++11".}

{.emit: """

#include <memory>
#include <iostream>

class TestObj;

typedef std::shared_ptr<TestObj> TestObjRef;

class TestObj {
public:
  void sayHello() {
    std::cout << "Hello from cpp" << std::endl;
  }

  static TestObjRef mkRef() {
    return std::make_shared<TestObj>();
  }
};

""".}

type
  TestObj {.importcpp: "TestObj".} = object
  TestObjRef {.importcpp: "TestObjRef".} = ptr TestObj

proc mkRef(): TestObjRef {.importcpp: "TestObj::mkRef".}
proc sayHello(o: TestObj) {.importcpp: "sayHello".}

when isMainModule:
  echo "Hello from nim"
  mkRef()[].sayHello()

, but the import for this line is broken:

type TestObjRef {.importcpp: "TestObjRef".} = ptr TestObj

The compiler generates this definition in cpp code:

N_NIMCALL(TestObj*, TestObj::mkRef)(void);

But it must use imported symbol, like this:

N_NIMCALL(TestObjRef, TestObj::mkRef)(void);
@vegansk
Copy link
Contributor Author

vegansk commented Nov 26, 2015

When I changed N_NIMCALL(TestObj*, TestObj::mkRef)(void); to N_NIMCALL(TestObjRef, TestObj::mkRef)(void); in generated cpp and compiled it manually, the executable works as expected. The output:

Hello from nim
Hello from cpp

@vegansk
Copy link
Contributor Author

vegansk commented Nov 26, 2015

Found the ugly workaround:

####################################################################################################
# RAII test for C++ FFI

{.passC: "-std=c++11".}

{.emit: """

#include <memory>
#include <iostream>

class TestObj;

typedef std::shared_ptr<TestObj> TestObjRef;

class TestObj {
private: 
  TestObj(const TestObj&) = delete;
  TestObj() {}
public:
  void sayHello() {
    std::cout << "Hello from cpp" << std::endl;
  }

  static TestObjRef mkRef() {
    return std::shared_ptr<TestObj>(new TestObj);
  }
};

""".}

type
  TestObj {.importcpp: "TestObj".} = object
  TestObjRef {.importcpp: "TestObjRef".} = object

proc mkRef(): TestObjRef {.importcpp: "TestObj::mkRef".}
proc sayHello(o: TestObj) {.importcpp: "sayHello".}

proc get(o: TestObjRef): ptr TestObj =
  {.emit: """
    return `o`.get();
  """.}

{.experimental.}

when isMainModule:
  echo "Hello from nim"
  mkRef().get.sayHello()

@Araq
Copy link
Member

Araq commented Nov 26, 2015

But it must use imported symbol, like this: ...

No, it doesn't. 'importcpp' cannot ever work for structural types ("ptr", "ref", etc.). The compiler should complain though.

@stale
Copy link

stale bot commented Aug 4, 2020

This issue has been automatically marked as stale because it has not had recent activity. If you think it is still a valid issue, write a comment below; otherwise it will be closed. Thank you for your contributions.

@stale stale bot added the stale Staled PR/issues; remove the label after fixing them label Aug 4, 2020
@ringabout
Copy link
Member

ringabout commented Jan 9, 2021

The original bug disappeared, but the origin issue remains.

####################################################################################################
# RAII test for C++ FFI

{.passC: "-std=c++11".}

{.emit: """

#include <memory>
#include <iostream>

class TestObj;

typedef std::shared_ptr<TestObj> TestObjRef;

class TestObj {
public:
  void sayHello() {
    std::cout << "Hello from cpp" << std::endl;
  }

  static TestObjRef mkRef() {
    return std::make_shared<TestObj>();
  }
};

""".}

type
  TestObj {.importcpp: "TestObj".} = object
  TestObjRef {.importcpp: "TestObjRef".} = ptr TestObj

proc mkRef(): TestObjRef {.importcpp: "TestObj::mkRef".}
proc sayHello(o: TestObj) {.importcpp: "sayHello".}



when isMainModule:
  echo "Hello from nim"
  var x = mkRef()
  x[].sayHello()
D:\QQPCmgr\Desktop\Nim\nimcache\@mpair.nim.cpp:125:45: error: cannot convert 'TestObjRef' {aka 'std::shared_ptr<TestObj>'} to 
'TestObj*' in assignment
  x__dsFjl2lRPq4IlK7mt0XcOw = TestObj::mkRef();

@stale stale bot removed the stale Staled PR/issues; remove the label after fixing them label Jan 9, 2021
@timotheecour
Copy link
Member

timotheecour commented Jan 9, 2021

this works:

#include <memory>
#include <iostream>

class TestObj;

typedef std::shared_ptr<TestObj> TestObjRef;

class TestObj {
public:
  void sayHello() {
    std::cout << "Hello from cpp" << std::endl;
  }

  static TestObjRef mkRef() {
    return std::make_shared<TestObj>();
  }
};
when defined case5:
  {.passC: "-std=c++11".}

  type
    TestObj {.importcpp: "TestObj", header: "t11664c.h".} = object
    shared_ptr[T] {.importcpp: "std::shared_ptr", header:"<memory>".} = object
    TestObjRef = shared_ptr[TestObj]

  proc `[]`[T](a: shared_ptr[T]): T {.importcpp: "(*#)", header: "<memory>".}
  proc mkRef(): TestObjRef {.importcpp: "TestObj::mkRef", header: "t11664c.h".}
  proc sayHello(o: TestObj) {.importcpp: "sayHello", header: "t11664c.h".}

  when isMainModule:
    echo "Hello from nim"
    var x = mkRef()
    doAssert x is TestObjRef
    let x2 = x[]
    doAssert x2 is TestObj
    x[].sayHello()

we need more examples like that in manual or (preferably) some other dedicated section of manual dedicated to interop

TODO before closing this

  • add this as a regression test for C++ codgen
  • make type TestObjRef {.importcpp: "TestObjRef".} = ptr TestObj a CT error, and maybe even point to section of manual describing how to do what user intended
  • header shouldn't even be needed if you have emit section; right now this doesn't work

(alternatively, these items can be moved to some dedicated issue tracking them)

@timotheecour timotheecour added C++ Code Generation Invalid Code Acceptance Everything related to compiler not complaining about invalid code and removed Error Messages Low Priority labels Jan 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C++ Code Generation Invalid Code Acceptance Everything related to compiler not complaining about invalid code
Projects
None yet
Development

No branches or pull requests

4 participants