summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorsls1005 <90055573+sls1005@users.noreply.github.com>2023-09-18 22:42:43 +0800
committerGitHub <noreply@github.com>2023-09-18 16:42:43 +0200
commitdba9000609ef55dfbcf7391edd2d1375f8ea3a1e (patch)
treeac3d95d66c6d3fe4835d5ed4888cee7440d0d6a9 /lib
parent741285b335343ad61afc2d48778c52cd097d1249 (diff)
downloadNim-dba9000609ef55dfbcf7391edd2d1375f8ea3a1e.tar.gz
Add descriptions and examples for `rawProc` and `rawEnv` (#22710)
Add descriptions for `rawProc` and `rawEnv`. See
<https://forum.nim-lang.org/t/10485> for more informations.

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/system.nim32
1 files changed, 31 insertions, 1 deletions
diff --git a/lib/system.nim b/lib/system.nim
index 633f637ca..56fa91ee2 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2246,19 +2246,49 @@ when notJSnotNims:
 
   proc rawProc*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} =
     ## Retrieves the raw proc pointer of the closure `x`. This is
-    ## useful for interfacing closures with C/C++, hash compuations, etc.
+    ## useful for interfacing closures with C/C++, hash computations, etc.
+    ## If `rawEnv(x)` returns `nil`, the proc which the result points to
+    ## takes as many parameters as `x`, but with `{.nimcall.}` as its calling
+    ## convention instead of `{.closure.}`, otherwise it takes one more parameter
+    ## which is a `pointer`, and it still has `{.nimcall.}` as its calling convention.
+    ## To invoke the resulted proc, what this returns has to be casted into a `proc`,
+    ## not a `ptr proc`, and, in a case where `rawEnv(x)` returns non-`nil`,
+    ## the last and additional argument has to be the result of `rawEnv(x)`.
+    ## This is not available for the JS target.
     #[
     The conversion from function pointer to `void*` is a tricky topic, but this
     should work at least for c++ >= c++11, e.g. for `dlsym` support.
     refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869,
     https://stackoverflow.com/questions/14125474/casts-between-pointer-to-function-and-pointer-to-object-in-c-and-c
     ]#
+    runnableExamples:
+      proc makeClosure(x: int): (proc(y: int): int) =
+        var n = x
+        result = (
+          proc(y: int): int =
+            n += y
+            return n
+        )
+
+      var
+        c1 = makeClosure(10)
+        e = c1.rawEnv()
+        p = c1.rawProc()
+
+      if e.isNil():
+        let c2 = cast[proc(y: int): int {.nimcall.}](p)
+        echo c2(2)
+      else:
+        let c3 = cast[proc(y: int; env: pointer): int {.nimcall.}](p)
+        echo c3(3, e)
+
     {.emit: """
     `result` = (void*)`x`.ClP_0;
     """.}
 
   proc rawEnv*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} =
     ## Retrieves the raw environment pointer of the closure `x`. See also `rawProc`.
+    ## This is not available for the JS target.
     {.emit: """
     `result` = `x`.ClE_0;
     """.}