add curl example
Graham Ollis authored 1 year, 6 months ago
Graham✈️✈️ committed 1 year, 6 months ago
0 | 0 | Revision history for {{$dist->name}} |
1 | 1 | |
2 | 2 | {{$NEXT}} |
3 | - Documentation improvements (gh#372, gh#381, gh#382, gh#383, gh#384) | |
3 | - Documentation improvements (gh#372, gh#380, gh#381, gh#382, gh#383, gh#384, | |
4 | gh#386) | |
4 | 5 | |
5 | 6 | 2.03 2022-10-27 21:19:06 -0600 |
6 | 7 | - Add hook for detecting bundled Zig project. You will need to install |
1703 | 1703 | use FFI::Platypus::Buffer qw( scalar_to_buffer window ); |
1704 | 1704 | |
1705 | 1705 | my $endpoint = "ipc://zmq-ffi-$$"; |
1706 | my $ffi = FFI::Platypus->new( api => 2 ); | |
1707 | ||
1708 | $ffi->lib(undef); # for puts | |
1709 | $ffi->attach(puts => ['string'] => 'int'); | |
1710 | ||
1711 | $ffi->lib(find_lib_or_die lib => 'zmq'); | |
1706 | my $ffi = FFI::Platypus->new( | |
1707 | api => 2, | |
1708 | lib => find_lib_or_die lib => 'zmq', | |
1709 | ); | |
1710 | ||
1712 | 1711 | $ffi->attach(zmq_version => ['int*', 'int*', 'int*'] => 'void'); |
1713 | 1712 | |
1714 | 1713 | my($major,$minor,$patch); |
1715 | 1714 | zmq_version(\$major, \$minor, \$patch); |
1716 | puts("libzmq version $major.$minor.$patch"); | |
1715 | print "libzmq version $major.$minor.$patch\n"; | |
1717 | 1716 | die "this script only works with libzmq 3 or better" unless $major >= 3; |
1718 | 1717 | |
1719 | 1718 | $ffi->type('opaque' => 'zmq_context'); |
1810 | 1809 | # the ArchiveWrite class that could be used for writing archive formats |
1811 | 1810 | # supported by libarchive |
1812 | 1811 | |
1813 | my $ffi = FFI::Platypus->new( api => 2 ); | |
1814 | $ffi->lib(find_lib_or_die lib => 'archive'); | |
1812 | my $ffi = FFI::Platypus->new( | |
1813 | api => 2, | |
1814 | lib => find_lib_or_die(lib => 'archive'), | |
1815 | ); | |
1815 | 1816 | $ffi->type('object(Archive)' => 'archive_t'); |
1816 | 1817 | $ffi->type('object(ArchiveRead)' => 'archive_read_t'); |
1817 | 1818 | $ffi->type('object(ArchiveWrite)' => 'archive_write_t'); |
2017 | 2018 | of `opaque` (the latter being the default for the `object` type). |
2018 | 2019 | Mainly just for demonstration since Perl has much better IO libraries, |
2019 | 2020 | but now we have an OO interface to the Unix IO functions. |
2021 | ||
2022 | ## Varadic Functions (with libcurl) | |
2023 | ||
2024 | ### C API | |
2025 | ||
2026 | - [curl\_easy\_init](https://curl.se/libcurl/c/curl_easy_init.html) | |
2027 | - [curl\_easy\_setopt](https://curl.se/libcurl/c/curl_easy_setopt.html) | |
2028 | - [curl\_easy\_perform](https://curl.se/libcurl/c/curl_easy_perform.html) | |
2029 | - [curl\_easy\_cleanup](https://curl.se/libcurl/c/curl_easy_cleanup.html) | |
2030 | ||
2031 | ### Perl Source | |
2032 | ||
2033 | ```perl | |
2034 | use FFI::Platypus 2.00; | |
2035 | use FFI::CheckLib qw( find_lib_or_die ); | |
2036 | use constant CURLOPT_URL => 10002; | |
2037 | ||
2038 | my $ffi = FFI::Platypus->new( | |
2039 | api => 2, | |
2040 | lib => find_lib_or_die(lib => 'curl'), | |
2041 | ); | |
2042 | ||
2043 | # https://curl.se/libcurl/c/curl_easy_init.html | |
2044 | my $curl_handle = $ffi->function( 'curl_easy_init' => [] => 'opaque' ) | |
2045 | ->call; | |
2046 | ||
2047 | # https://curl.se/libcurl/c/curl_easy_setopt.html | |
2048 | $ffi->function( 'curl_easy_setopt' => ['opaque', 'enum' ] => ['string'] ) | |
2049 | ->call($curl_handle, CURLOPT_URL, "https://pl.atypus.org" ); | |
2050 | ||
2051 | # https://curl.se/libcurl/c/curl_easy_perform.html | |
2052 | $ffi->function( 'curl_easy_perform' => ['opaque' ] => 'enum' ) | |
2053 | ->call($curl_handle); | |
2054 | ||
2055 | # https://curl.se/libcurl/c/curl_easy_cleanup.html | |
2056 | $ffi->function( 'curl_easy_cleanup' => ['opaque' ] ) | |
2057 | ->call($curl_handle); | |
2058 | ``` | |
2059 | ||
2060 | ### Execute | |
2061 | ||
2062 | ``` | |
2063 | $ perl curl.pl | |
2064 | <!doctype html> | |
2065 | <html lang="en"> | |
2066 | <head> | |
2067 | <meta charset="utf-8" /> | |
2068 | <title>pl.atypus.org - Home for the Perl Platypus Project</title> | |
2069 | ... | |
2070 | ``` | |
2071 | ||
2072 | ### Discussion | |
2073 | ||
2074 | The `libcurl` library makes extensive use of "varadic" functions. | |
2075 | ||
2076 | The C programming language and ABI have the concept of "varadic" functions | |
2077 | that can take a variable number and variable type of arguments. Assuming | |
2078 | you have a `libffi` that supports it (and most modern systems should), | |
2079 | then you can create bindings to a varadic function by providing two sets | |
2080 | of array references, one for the fixed arguments (for reasons, C varadic | |
2081 | functions must have at least one) and one for variable arguments. In | |
2082 | this example we call `curl_easy_setopt` as a varadic function. | |
2083 | ||
2084 | For functions that have a large or infinite number of possible signatures | |
2085 | it may be impracticable or impossible to attach them all. You can instead | |
2086 | do as we did in this example, create a function object using the | |
2087 | [function method](#function) and call it immediately. This is not as | |
2088 | performant either when you create or call as using the [attach method](#attach), | |
2089 | but in some cases the performance penalty may be worth it or unavoidable. | |
2020 | 2090 | |
2021 | 2091 | ## bundle your own code |
2022 | 2092 |
159 | 159 | - NULLs |
160 | 160 | - XORd |
161 | 161 | - decrypted |
162 | - varadic | |
163 | - libcurl | |
164 | - performant | |
162 | 165 | |
163 | 166 | pod_coverage: |
164 | 167 | skip: 0 |
7 | 7 | # the ArchiveWrite class that could be used for writing archive formats |
8 | 8 | # supported by libarchive |
9 | 9 | |
10 | my $ffi = FFI::Platypus->new( api => 2 ); | |
11 | $ffi->lib(find_lib_or_die lib => 'archive'); | |
10 | my $ffi = FFI::Platypus->new( | |
11 | api => 2, | |
12 | lib => find_lib_or_die(lib => 'archive'), | |
13 | ); | |
12 | 14 | $ffi->type('object(Archive)' => 'archive_t'); |
13 | 15 | $ffi->type('object(ArchiveRead)' => 'archive_read_t'); |
14 | 16 | $ffi->type('object(ArchiveWrite)' => 'archive_write_t'); |
0 | use strict; | |
1 | use warnings; | |
2 | use FFI::Platypus 2.00; | |
3 | use FFI::CheckLib qw( find_lib_or_die ); | |
4 | use constant CURLOPT_URL => 10002; | |
5 | ||
6 | my $ffi = FFI::Platypus->new( | |
7 | api => 2, | |
8 | lib => find_lib_or_die(lib => 'curl'), | |
9 | ); | |
10 | ||
11 | # https://curl.se/libcurl/c/curl_easy_init.html | |
12 | my $curl_handle = $ffi->function( 'curl_easy_init' => [] => 'opaque' ) | |
13 | ->call; | |
14 | ||
15 | # https://curl.se/libcurl/c/curl_easy_setopt.html | |
16 | $ffi->function( 'curl_easy_setopt' => ['opaque', 'enum' ] => ['string'] ) | |
17 | ->call($curl_handle, CURLOPT_URL, "https://pl.atypus.org" ); | |
18 | ||
19 | # https://curl.se/libcurl/c/curl_easy_perform.html | |
20 | $ffi->function( 'curl_easy_perform' => ['opaque' ] => 'enum' ) | |
21 | ->call($curl_handle); | |
22 | ||
23 | # https://curl.se/libcurl/c/curl_easy_cleanup.html | |
24 | $ffi->function( 'curl_easy_cleanup' => ['opaque' ] ) | |
25 | ->call($curl_handle); |
9 | 9 | use FFI::Platypus::Buffer qw( scalar_to_buffer window ); |
10 | 10 | |
11 | 11 | my $endpoint = "ipc://zmq-ffi-$$"; |
12 | my $ffi = FFI::Platypus->new( api => 2 ); | |
12 | my $ffi = FFI::Platypus->new( | |
13 | api => 2, | |
14 | lib => find_lib_or_die lib => 'zmq', | |
15 | ); | |
13 | 16 | |
14 | $ffi->lib(undef); # for puts | |
15 | $ffi->attach(puts => ['string'] => 'int'); | |
16 | ||
17 | $ffi->lib(find_lib_or_die lib => 'zmq'); | |
18 | 17 | $ffi->attach(zmq_version => ['int*', 'int*', 'int*'] => 'void'); |
19 | 18 | |
20 | 19 | my($major,$minor,$patch); |
21 | 20 | zmq_version(\$major, \$minor, \$patch); |
22 | puts("libzmq version $major.$minor.$patch"); | |
21 | print "libzmq version $major.$minor.$patch\n"; | |
23 | 22 | die "this script only works with libzmq 3 or better" unless $major >= 3; |
24 | 23 | |
25 | 24 | $ffi->type('opaque' => 'zmq_context'); |
1925 | 1925 | Mainly just for demonstration since Perl has much better IO libraries, |
1926 | 1926 | but now we have an OO interface to the Unix IO functions. |
1927 | 1927 | |
1928 | =head2 Varadic Functions (with libcurl) | |
1929 | ||
1930 | =head3 C API | |
1931 | ||
1932 | =over 4 | |
1933 | ||
1934 | =item L<curl_easy_init|https://curl.se/libcurl/c/curl_easy_init.html> | |
1935 | ||
1936 | =item L<curl_easy_setopt|https://curl.se/libcurl/c/curl_easy_setopt.html> | |
1937 | ||
1938 | =item L<curl_easy_perform|https://curl.se/libcurl/c/curl_easy_perform.html> | |
1939 | ||
1940 | =item L<curl_easy_cleanup|https://curl.se/libcurl/c/curl_easy_cleanup.html> | |
1941 | ||
1942 | =back | |
1943 | ||
1944 | =head3 Perl Source | |
1945 | ||
1946 | # EXAMPLE: examples/curl.pl | |
1947 | ||
1948 | =head3 Execute | |
1949 | ||
1950 | $ perl curl.pl | |
1951 | <!doctype html> | |
1952 | <html lang="en"> | |
1953 | <head> | |
1954 | <meta charset="utf-8" /> | |
1955 | <title>pl.atypus.org - Home for the Perl Platypus Project</title> | |
1956 | ... | |
1957 | ||
1958 | =head3 Discussion | |
1959 | ||
1960 | The C<libcurl> library makes extensive use of "varadic" functions. | |
1961 | ||
1962 | The C programming language and ABI have the concept of "varadic" functions | |
1963 | that can take a variable number and variable type of arguments. Assuming | |
1964 | you have a C<libffi> that supports it (and most modern systems should), | |
1965 | then you can create bindings to a varadic function by providing two sets | |
1966 | of array references, one for the fixed arguments (for reasons, C varadic | |
1967 | functions must have at least one) and one for variable arguments. In | |
1968 | this example we call C<curl_easy_setopt> as a varadic function. | |
1969 | ||
1970 | For functions that have a large or infinite number of possible signatures | |
1971 | it may be impracticable or impossible to attach them all. You can instead | |
1972 | do as we did in this example, create a function object using the | |
1973 | L<function method|/function> and call it immediately. This is not as | |
1974 | performant either when you create or call as using the L<attach method|/attach>, | |
1975 | but in some cases the performance penalty may be worth it or unavoidable. | |
1976 | ||
1928 | 1977 | =head2 bundle your own code |
1929 | 1978 | |
1930 | 1979 | C<ffi/foo.c>: |