functionalscript 0.0.463 → 0.0.465
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/com.yml +4 -1
- package/Cargo.lock +1 -1
- package/com/cpp/com.hpp +96 -2
- package/com/cpp/module.f.cjs +11 -3
- package/com/cpp/test.f.cjs +2 -1
- package/com/rust/nanocom/Cargo.toml +1 -1
- package/com/rust/nanocom/src/cobject.rs +2 -10
- package/com/rust/nanocom/src/guid.rs +14 -0
- package/com/test/build.f.cjs +8 -4
- package/com/test/cpp/main.cpp +29 -2
- package/com/test/cs/Program.cs +7 -2
- package/com/test/rust/src/lib.rs +4 -2
- package/package.json +1 -1
|
@@ -19,10 +19,13 @@ jobs:
|
|
|
19
19
|
runs-on: ${{ matrix.os }}
|
|
20
20
|
|
|
21
21
|
steps:
|
|
22
|
-
- uses: actions/checkout@
|
|
22
|
+
- uses: actions/checkout@v3
|
|
23
23
|
- name: Use Node.js 19
|
|
24
24
|
uses: actions/setup-node@v2
|
|
25
25
|
with:
|
|
26
26
|
node-version: 19
|
|
27
|
+
- uses: actions/setup-dotnet@v3
|
|
28
|
+
with:
|
|
29
|
+
dotnet-version: 7
|
|
27
30
|
- run: npm ci
|
|
28
31
|
- run: npm run comtest
|
package/Cargo.lock
CHANGED
package/com/cpp/com.hpp
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
#include <cstdint>
|
|
4
4
|
#include <cstddef>
|
|
5
|
+
#include <atomic>
|
|
6
|
+
#include <iostream>
|
|
5
7
|
|
|
6
8
|
#if defined(__aarch64__) || defined(__amd64__)
|
|
7
9
|
#define COM_STDCALL
|
|
@@ -13,15 +15,62 @@
|
|
|
13
15
|
|
|
14
16
|
namespace com
|
|
15
17
|
{
|
|
18
|
+
constexpr uint64_t byteswap(uint64_t v)
|
|
19
|
+
{
|
|
20
|
+
v = v >> 8 & 0x00FF00FF00FF00FF |
|
|
21
|
+
v << 8 & 0xFF00FF00FF00FF00;
|
|
22
|
+
v = v >> 16 & 0x0000FFFF0000FFFF |
|
|
23
|
+
v << 16 & 0xFFFF0000FFFF0000;
|
|
24
|
+
return v >> 32 | v << 32;
|
|
25
|
+
}
|
|
26
|
+
|
|
16
27
|
class GUID
|
|
17
28
|
{
|
|
18
29
|
public:
|
|
19
|
-
uint64_t hi;
|
|
20
30
|
uint64_t lo;
|
|
31
|
+
uint64_t hi;
|
|
32
|
+
constexpr GUID(uint64_t const lo, uint64_t const hi) noexcept
|
|
33
|
+
: lo(lo << 48 & 0xFFFF'0000'0000'0000 |
|
|
34
|
+
lo << 16 & 0x0000'FFFF'0000'0000 |
|
|
35
|
+
lo >> 32),
|
|
36
|
+
hi(byteswap(hi))
|
|
37
|
+
{
|
|
38
|
+
}
|
|
39
|
+
constexpr bool operator==(GUID const b) const noexcept
|
|
40
|
+
{
|
|
41
|
+
return lo == b.lo && hi == b.hi;
|
|
42
|
+
}
|
|
43
|
+
constexpr bool operator!=(GUID const b) const noexcept
|
|
44
|
+
{
|
|
45
|
+
return !(*this == b);
|
|
46
|
+
}
|
|
21
47
|
};
|
|
22
48
|
|
|
49
|
+
inline void guid_part(std::ostream &os, uint64_t const v)
|
|
50
|
+
{
|
|
51
|
+
for (int i = 64; i > 0;)
|
|
52
|
+
{
|
|
53
|
+
i -= 4;
|
|
54
|
+
char const c = (v >> i) & 0xF;
|
|
55
|
+
char const x = c < 10 ? c + '0' : c + ('A' - 10);
|
|
56
|
+
os << x;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
inline std::ostream &operator<<(std::ostream &os, GUID const &self)
|
|
61
|
+
{
|
|
62
|
+
guid_part(os, self.lo);
|
|
63
|
+
guid_part(os, self.hi);
|
|
64
|
+
return os;
|
|
65
|
+
}
|
|
66
|
+
|
|
23
67
|
typedef uint32_t HRESULT;
|
|
68
|
+
|
|
69
|
+
static HRESULT const E_NOINTERFACE = 0x80004002;
|
|
70
|
+
static HRESULT const S_OK = 0;
|
|
71
|
+
|
|
24
72
|
typedef uint32_t ULONG;
|
|
73
|
+
|
|
25
74
|
typedef int32_t BOOL;
|
|
26
75
|
|
|
27
76
|
class IUnknown
|
|
@@ -36,7 +85,7 @@ namespace com
|
|
|
36
85
|
class ref
|
|
37
86
|
{
|
|
38
87
|
public:
|
|
39
|
-
explicit ref(I &other) noexcept : p(other
|
|
88
|
+
explicit ref(I &other) noexcept : p(other)
|
|
40
89
|
{
|
|
41
90
|
p.AddRef();
|
|
42
91
|
}
|
|
@@ -47,7 +96,52 @@ namespace com
|
|
|
47
96
|
{
|
|
48
97
|
p.Release();
|
|
49
98
|
}
|
|
99
|
+
|
|
50
100
|
private:
|
|
51
101
|
I &p;
|
|
52
102
|
};
|
|
103
|
+
|
|
104
|
+
constexpr static GUID const iunknown_guid =
|
|
105
|
+
GUID(0x00000000'0000'0000, 0xC000'000000000046);
|
|
106
|
+
|
|
107
|
+
template <class I>
|
|
108
|
+
constexpr GUID interface_guid();
|
|
109
|
+
|
|
110
|
+
template <class T>
|
|
111
|
+
class implementation : public T
|
|
112
|
+
{
|
|
113
|
+
private:
|
|
114
|
+
HRESULT COM_STDCALL QueryInterface(GUID const &riid, IUnknown **const ppvObject) noexcept override
|
|
115
|
+
{
|
|
116
|
+
if (riid != iunknown_guid && riid != T::guid)
|
|
117
|
+
{
|
|
118
|
+
return E_NOINTERFACE;
|
|
119
|
+
}
|
|
120
|
+
add_ref();
|
|
121
|
+
*ppvObject = this;
|
|
122
|
+
return S_OK;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
ULONG add_ref() noexcept
|
|
126
|
+
{
|
|
127
|
+
return counter.fetch_add(1);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
ULONG COM_STDCALL AddRef() noexcept override
|
|
131
|
+
{
|
|
132
|
+
return add_ref() + 1;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
ULONG COM_STDCALL Release() noexcept override
|
|
136
|
+
{
|
|
137
|
+
auto const c = counter.fetch_sub(1) - 1;
|
|
138
|
+
if (c == 0)
|
|
139
|
+
{
|
|
140
|
+
delete this;
|
|
141
|
+
}
|
|
142
|
+
return c;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
std::atomic<ULONG> counter;
|
|
146
|
+
};
|
|
53
147
|
}
|
package/com/cpp/module.f.cjs
CHANGED
|
@@ -5,7 +5,7 @@ const obj = require('../../types/object/module.f.cjs')
|
|
|
5
5
|
const list = require('../../types/list/module.f.cjs')
|
|
6
6
|
const { map, flatMap, flat } = list
|
|
7
7
|
const { join } = require('../../types/string/module.f.cjs')
|
|
8
|
-
const { entries } =
|
|
8
|
+
const { entries } = Object
|
|
9
9
|
|
|
10
10
|
/** @type {(name: string) => (body: text.Block) => text.Block} */
|
|
11
11
|
const struct = name => body => [`struct ${name}`, '{', body, '};']
|
|
@@ -70,12 +70,20 @@ const cpp = name => lib => {
|
|
|
70
70
|
const mapMethod = map(method)
|
|
71
71
|
|
|
72
72
|
/** @type {(i: types.Interface) => text.Block} */
|
|
73
|
-
const defInterface = i =>
|
|
73
|
+
const defInterface = ({ guid, interface: i }) => {
|
|
74
|
+
const g = guid.replaceAll('-', '');
|
|
75
|
+
const lo = g.substring(0, 16);
|
|
76
|
+
const hi = g.substring(16);
|
|
77
|
+
return flat([
|
|
78
|
+
[`constexpr static ::com::GUID const guid = ::com::GUID(0x${lo}, 0x${hi});`],
|
|
79
|
+
mapMethod(entries(i))
|
|
80
|
+
])
|
|
81
|
+
}
|
|
74
82
|
|
|
75
83
|
/** @type {(kv: obj.Entry<types.Definition>) => text.Block} */
|
|
76
84
|
const def = ([name, d]) => d.interface === undefined
|
|
77
85
|
? struct(name)(defStruct(d))
|
|
78
|
-
: struct(`${name}: ::com::IUnknown`)(defInterface(d))
|
|
86
|
+
: struct(`${name} : ::com::IUnknown`)(defInterface(d))
|
|
79
87
|
|
|
80
88
|
/** @type {(kv: obj.Entry<types.Definition>) => text.Block} */
|
|
81
89
|
const forward = ([name]) => [`struct ${name};`]
|
package/com/cpp/test.f.cjs
CHANGED
|
@@ -19,8 +19,9 @@ const f = () =>
|
|
|
19
19
|
' {\n' +
|
|
20
20
|
' ::com::ref<IMy> M;\n' +
|
|
21
21
|
' };\n' +
|
|
22
|
-
' struct IMy: ::com::IUnknown\n' +
|
|
22
|
+
' struct IMy : ::com::IUnknown\n' +
|
|
23
23
|
' {\n' +
|
|
24
|
+
' constexpr static ::com::GUID const guid = ::com::GUID(0xC66FB2702D8049AD, 0xBB6E88C1F90B805D);\n' +
|
|
24
25
|
' virtual Slice COM_STDCALL GetSlice() noexcept = 0;\n' +
|
|
25
26
|
' virtual void COM_STDCALL SetSlice(Slice slice) noexcept = 0;\n' +
|
|
26
27
|
' virtual ::com::BOOL* COM_STDCALL GetUnsafe() noexcept = 0;\n' +
|
|
@@ -3,7 +3,7 @@ use std::{
|
|
|
3
3
|
sync::atomic::{AtomicU32, Ordering},
|
|
4
4
|
};
|
|
5
5
|
|
|
6
|
-
use crate::{hresult::HRESULT, iunknown::IUnknown, Class,
|
|
6
|
+
use crate::{guid::GuidEx, hresult::HRESULT, iunknown::IUnknown, Class, Object, Ref};
|
|
7
7
|
|
|
8
8
|
#[repr(C)]
|
|
9
9
|
pub struct CObject<T: Class> {
|
|
@@ -12,14 +12,6 @@ pub struct CObject<T: Class> {
|
|
|
12
12
|
pub value: T,
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const fn guid<I: Interface>() -> u128 {
|
|
16
|
-
let x = <I>::GUID;
|
|
17
|
-
(x >> 96) |
|
|
18
|
-
((x >> 48) & 0x00000_000_0000_0000_0000_FFFF_0000_0000) |
|
|
19
|
-
((x >> 16) & 0x0000_0000_0000_0000_FFFF_0000_0000_0000) |
|
|
20
|
-
(((x as u64).swap_bytes() as u128) << 64)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
15
|
impl<T: Class> CObject<T> {
|
|
24
16
|
pub const IUNKNOWN: IUnknown<T::Interface> = IUnknown {
|
|
25
17
|
QueryInterface: Self::QueryInterface,
|
|
@@ -38,7 +30,7 @@ impl<T: Class> CObject<T> {
|
|
|
38
30
|
riid: &u128,
|
|
39
31
|
ppv_object: &mut *const Object,
|
|
40
32
|
) -> HRESULT {
|
|
41
|
-
let (p, r) = if *riid ==
|
|
33
|
+
let (p, r) = if *riid == <()>::PLATFORM_GUID || *riid == T::Interface::PLATFORM_GUID {
|
|
42
34
|
Self::AddRef(this);
|
|
43
35
|
(this.to_iunknown() as *const Object, HRESULT::S_OK)
|
|
44
36
|
} else {
|
|
@@ -1 +1,15 @@
|
|
|
1
|
+
use crate::Interface;
|
|
2
|
+
|
|
1
3
|
pub type GUID = u128;
|
|
4
|
+
|
|
5
|
+
pub trait GuidEx: Interface {
|
|
6
|
+
const PLATFORM_GUID: GUID = {
|
|
7
|
+
let x = Self::GUID;
|
|
8
|
+
(x >> 96)
|
|
9
|
+
| ((x >> 48) & 0x00000_000_0000_0000_0000_FFFF_0000_0000)
|
|
10
|
+
| ((x >> 16) & 0x0000_0000_0000_0000_FFFF_0000_0000_0000)
|
|
11
|
+
| (((x as u64).swap_bytes() as u128) << 64)
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
impl<T: Interface> GuidEx for T {}
|
package/com/test/build.f.cjs
CHANGED
|
@@ -46,9 +46,9 @@ const flags = platform => {
|
|
|
46
46
|
case 'win32':
|
|
47
47
|
return []
|
|
48
48
|
case 'linux':
|
|
49
|
-
return ['-lstdc++']
|
|
49
|
+
return ['-lstdc++', '-fPIC']
|
|
50
50
|
default:
|
|
51
|
-
return ['-std=c++
|
|
51
|
+
return ['-std=c++17', '-lc++']
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -77,13 +77,17 @@ const cpp = ({dirname, platform}) => ({
|
|
|
77
77
|
})
|
|
78
78
|
|
|
79
79
|
/** @type {Func} */
|
|
80
|
-
const cs = ({dirname}) => ({
|
|
80
|
+
const cs = ({dirname, platform}) => ({
|
|
81
81
|
file: {
|
|
82
82
|
name: `${dirname}/cs/_result.cs`,
|
|
83
83
|
content: csContent,
|
|
84
84
|
},
|
|
85
85
|
line: [
|
|
86
|
-
|
|
86
|
+
platform === 'win32'
|
|
87
|
+
? ['dotnet', 'run', '--project', `${dirname}/cs/cs.csproj`]
|
|
88
|
+
// .Net on Linux and Windows doesn't properly support COM object marshalling
|
|
89
|
+
: ['dotnet', 'build', `${dirname}/cs/cs.csproj`]
|
|
90
|
+
],
|
|
87
91
|
})
|
|
88
92
|
|
|
89
93
|
/** @type {Func} */
|
package/com/test/cpp/main.cpp
CHANGED
|
@@ -13,6 +13,33 @@ extern "C" int c_get()
|
|
|
13
13
|
return 43;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
class Impl: My::IMy
|
|
17
|
-
|
|
16
|
+
class Impl: public My::IMy
|
|
17
|
+
{
|
|
18
|
+
My::Slice COM_STDCALL GetSlice() noexcept override
|
|
19
|
+
{
|
|
20
|
+
}
|
|
21
|
+
void COM_STDCALL SetSlice(My::Slice slice) noexcept override
|
|
22
|
+
{
|
|
23
|
+
}
|
|
24
|
+
::com::BOOL *COM_STDCALL GetUnsafe() noexcept override
|
|
25
|
+
{
|
|
26
|
+
}
|
|
27
|
+
void COM_STDCALL SetUnsafe(My::Slice *p, uint32_t size) noexcept override
|
|
28
|
+
{
|
|
29
|
+
}
|
|
30
|
+
::com::BOOL COM_STDCALL Some(My::IMy &p) noexcept override
|
|
31
|
+
{
|
|
32
|
+
}
|
|
33
|
+
::com::ref<My::IMy> COM_STDCALL GetIMy() noexcept override
|
|
34
|
+
{
|
|
35
|
+
}
|
|
36
|
+
void COM_STDCALL SetManagedStruct(My::ManagedStruct a) noexcept override
|
|
37
|
+
{
|
|
38
|
+
}
|
|
18
39
|
};
|
|
40
|
+
|
|
41
|
+
DLL_EXPORT
|
|
42
|
+
extern "C" My::IMy* c_my_create()
|
|
43
|
+
{
|
|
44
|
+
return new ::com::implementation<Impl>();
|
|
45
|
+
}
|
package/com/test/cs/Program.cs
CHANGED
|
@@ -10,10 +10,15 @@ static extern IMy rust_my_create();
|
|
|
10
10
|
[DllImport("testc")]
|
|
11
11
|
static extern int c_get();
|
|
12
12
|
|
|
13
|
+
[DllImport("testc")]
|
|
14
|
+
static extern IMy c_my_create();
|
|
15
|
+
|
|
13
16
|
// See https://aka.ms/new-console-template for more information
|
|
14
17
|
Console.WriteLine("Hello, World!");
|
|
15
18
|
Console.WriteLine(get());
|
|
16
19
|
Console.WriteLine(c_get());
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
var x = rust_my_create();
|
|
22
|
+
x.SetSlice(new Slice { Start = null, Size = (UIntPtr)44 });
|
|
23
|
+
|
|
24
|
+
var y = c_my_create();
|
package/com/test/rust/src/lib.rs
CHANGED
|
@@ -46,9 +46,11 @@ impl _result::IMy::Ex for nanocom::CObject<My> {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
#[no_mangle]
|
|
49
|
-
pub extern "C" fn get() -> i32 {
|
|
49
|
+
pub extern "C" fn get() -> i32 {
|
|
50
|
+
42
|
|
51
|
+
}
|
|
50
52
|
|
|
51
53
|
#[no_mangle]
|
|
52
54
|
pub extern "C" fn rust_my_create() -> IMy::Ref {
|
|
53
55
|
My {}.to_cobject()
|
|
54
|
-
}
|
|
56
|
+
}
|