cysharp / csbindgen Goto Github PK
View Code? Open in Web Editor NEWGenerate C# FFI from Rust for automatically brings native code and C native library to .NET and Unity.
License: MIT License
Generate C# FFI from Rust for automatically brings native code and C native library to .NET and Unity.
License: MIT License
Hi,
Can it be used for using c# within Rust (i.e. c# to rust)?
I've installed libpng via vcpkg.
The problem is that struct png_row_info_struct
, which bindgen
did generate, is not generated by csbindgen
.
The following source code is about as much as we can reproduce the problem.
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
// bindgen::Builder::default()
// .header("C:/src/vcpkg/installed/x64-windows/include/libpng16/png.h")
// .header("C:/src/vcpkg/installed/x64-windows/include/libpng16/pngconf.h")
// .header("C:/src/vcpkg/installed/x64-windows/include/libpng16/pnglibconf.h")
// .generate()
// .unwrap()
// .write_to_file("src/libpng16.rs")
// .unwrap();
csbindgen::Builder::new()
.input_bindgen_file("src/libpng16.rs")
//.method_filter(|x| x.starts_with("png_"))
.csharp_namespace("PixivApi.ImageFile")
.csharp_class_name("LibPng16")
.csharp_dll_name("libpng16")
.generate_csharp_file("../src/PixivApi.ImageFile/libpng16_csbindgen.cs")?;
Ok(())
}
Hi,
We currently have to write static callback to get a future response from a Rust function. Example:
unsafe
{
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
static void MyCallback()
{
// Ok callback
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
static void MyErrorCallback(byte* cString)
{
// Error callback
}
NativeMethods.fn(
&MyCallback,
&MyErrorCallback
);
}
Would it be possible to use create Action
this way so that we can stay in the same context:
unsafe
{
var callback = () =>
{
// Ok callback
};
var errorCallback = (byte* cString) =>
{
// Error callback
};
NativeMethods.fn(
&callback,
&errorCallback
);
}
error: failed to run custom build command for rust_to_cs v0.1.0 (/Users/anton/CLionProjects/rust_to_cs)
Caused by:
process didn't exit successfully: /Users/anton/CLionProjects/rust_to_cs/target/debug/build/rust_to_cs-6a3f9f0f0bafc3d7/build-script-build
(exit status: 101)
--- stderr
thread 'main' panicked at 'input file not found, path: /src/lib.rs: Os { code: 2, kind: NotFound, message: "No such file or directory" }', /Users/anton/.cargo/registry/src/github.com-1ecc6299db9ec823/csbindgen-1.7.3/src/lib.rs:40:14
note: run with RUST_BACKTRACE=1
environment variable to display a backtrace
Build.rs
fn main() { csbindgen::Builder::default() .input_extern_file("/src/lib.rs") .csharp_dll_name("nativelib") .generate_csharp_file("/dotnet/NativeMethods.g.cs") .unwrap(); }
lib.rs
#[no_mangle] pub extern "C" fn my_add(x: i32, y: i32) -> i32 { x + y }
like this:
public static extern bool Update([MarshalAs(UnmanagedType.LPUTF8Str)] String info1,long id, [MarshalAs(UnmanagedType.LPUTF8Str)] String info2);
Is it possible to read the data of unity in rust, and after calculation, return a unity object?
For example, read Vector3
and return List<Vector3>
in rust side?
1.9.2
Given the following Rust enum:
#[repr(C)]
pub enum CResultStatus {
Ok,
Err,
}
Version 1.8.0 generated the following csharp enum:
enum CResultStatus : uint
{
Ok,
Err,
}
whereas the new version generates:
enum CResultStatus : C
{
Ok,
Err,
}
dotnet then throws an error due to it not knowing what type C
is
Hello! I just found the library today and I've been playing around with it. But I may have found a few issues with the readme example (I could also be doing something very silly but I've looked around for a while)
I have a very simple program.cs file:
using CsBindgen;
Console.WriteLine(NativeMethods.my_add(1, 2));
I have a build.rs that looks like this:
fn main() {
csbindgen::Builder::default()
.input_extern_file("src/lib.rs")
.csharp_dll_name("nativelib")
.generate_csharp_file("./dotnet/NativeMethods.g.cs")
.unwrap();
}
with a src/lib.rs that looks like this:
// lib.rs, simple FFI code
#[no_mangle]
pub extern "C" fn my_add(x: i32, y: i32) -> i32 {
x + y
}
And a Cargo.toml file that looks like this:
[package]
name = "test-blob"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[build-dependencies]
csbindgen = "1.7.2"
When I run the code I get the C# File NativeMethods.g.cs that looks like this:
// <auto-generated>
// This code is generated by csbindgen.
// DON'T CHANGE THIS DIRECTLY.
// </auto-generated>
#pragma warning disable CS8500
#pragma warning disable CS8981
using System;
using System.Runtime.InteropServices;
namespace CsBindgen
{
internal static unsafe partial class NativeMethods
{
const string __DllName = "nativelib";
[DllImport(__DllName, EntryPoint = "my_add", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int my_add(int x, int y);
}
}
I've removed the "unsafe" keyword and change "internal" to "public" however, when I run dotnet run
I get this error
Hello, World!
Unhandled exception. System.DllNotFoundException: Unable to load DLL 'nativelib' or one of its dependencies: The specified module could not be found. (0x8007007E)
at CsBindgen.NativeMethods.my_add(Int32 x, Int32 y)
at Program.<Main>$(String[] args) in Program.cs:line 7
I've tried several methods of fixing this but it looks like the target folder from ``cargo build``` did not build the dll.
Do you know a way to fix this? This seems like a very silly error that I am making but I cannot seem to figure it out
Sorry for the messy text. I am trying to understand the historical layers here. Therefore, this is 60% question, 40% feature request.
I'll start with the fact that I am a bit confused about what calling convention actually is the default on which platform.
The Rust reference says something about the default here: https://doc.rust-lang.org/reference/items/external-blocks.html#abi. It says that cdecl
is only the default on x86_32, but on x86_64 the default is win64
, but on the forums it is said that extern "C"
is whatever LLVM considers to be the default. LLVM docs say that the default "C" calling convention is indeed cdecl
. https://llvm.org/doxygen/namespacellvm_1_1CallingConv.html
C#'s CallingConvention
enum doesn't even have a field for win64
, so I guess that calling convention isn't actually used much?
The question: Is cdecl
really the default everywhere?
This said, it would be useful, if we could configure the calling convention for the generated bindings. What if we do extern "stdcall" fn
in Rust? Currently, csbindgen doesn't pick it up.
Thanks for your cool project!
I was wondering if csbindgen
could have a way to rename struct/enums/constants, similarly to cbindgen with [export.rename]
?
I am creating a Rust library that will be used by a C# program. Most of my library is implemented without FFI in mind, and sometimes I need to convert structs from my library to semantically equivalent data structures that I can share through FFI. For example:
struct Configuration {
version: String
}
// ffi equivalent:
#[repr(C)]
struct Configuration {
version: *const c_char
}
This works well, but I have a naming clash: both structures are called Configuration
!
Ideally, I would like to keep using the original name in my lib, and use another name for the FFI version, for example:
struct Configuration {
version: String
}
// ffi equivalent:
#[repr(C)]
struct FfiConfiguration {
version: *const c_char
}
But when generating the C# file, I don't want those Ffi
prefixes, I'd prefer to expose the original name.
This could maybe be implemented as a new csbindgen::Builder
method, like so:
csbindgen::Builder::default()
.rename("FfiConfiguration", "Configuration")
how to use the csbindgen to make the ffmpeg c# bind?
require MarshalAsAttribute
I have a use case which requires parsing code which may be inside module blocks.
I want to support parsing macro expansions in my binding files, and I need macro expansions (at this point) only to support generic types.
The best way I found to support macro expansions is to run my code through cargo expand
to a temporary file, then ingest that with the csbindgen tool to generate the bindings. However, cargo expand will always wrap code inside nested module blocks.
In short, I need cargo expand to support macros which I can use to provide generic-like support. and Cargo expand generates code similar to the following example:
src/lib.rs:
pub mod interop_module{
#[no_mangle]
pub extern "C" fn triple_input(input: i32) -> i32 {
input * 3
}
}
build.rs:
fn main() {
csbindgen::Builder::default()
.input_extern_file("src/lib.rs")
.generate_csharp_file("target/dotnet/SystemRuntimeRust.g.cs")
.unwrap();
}
SystemRuntimeRust.g.cs:
//.. truncated usings
namespace CsBindgen
{
internal static unsafe partial class NativeMethods
{
const string __DllName = "";
[DllImport(__DllName, EntryPoint = "triple_input", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int triple_input(int input);
}
}
SystemRuntimeRust.g.cs:
//.. truncated usings
namespace CsBindgen
{
internal static unsafe partial class NativeMethods
{
const string __DllName = "";
}
}
Omitting the module wrapper produces the expected output:
src/lib.rs:
#[no_mangle]
pub extern "C" fn triple_input(input: i32) -> i32 {
input * 3
}
For my use case I want all the nested modules to automatically unwrap into the same output class. This does have the potential to cause typename collisions, but I believe that can be categorized as user error and would be pretty quickly obvious as a problem. I'm going to try to implement this in my fork of the repo.
I want to export a complex structure, but its internal definition does not need to be exposed to Csharp, and all its' interface using csharp type.
https://github.com/Cysharp/csbindgen#pointer is what I need, but I want to have some better output.
The flow I want is roughly as follows:
#[repr(C)]
pub struct CounterContext {
set: HashSet<i32>,
}
#[cs_bindgen(Box)] // or Rc, Arc, ...
// replace all self as Box<Self>, then can wrap by Box::into_raw and Box::from_raw
impl CounterContext {
#[cs_bindgen(constructor)]
pub fn create_counter_context() -> Self {
Self {
set: HashSet::new(),
}
}
// value is a csharp type
pub fn insert_counter_context(&mut self, value: i32) {
self.set.insert(value);
}
#[cs_bindgen(destructor))]
pub fn delete_counter_context(&mut self) {
for value in self.set.iter() {
println!("counter value: {}", value)
}
}
}
#[no_mangle]
pub extern "C" fn create_counter_context() -> *mut c_void {
let ctx = Box::new(CounterContext {
set: HashSet::new(),
});
Box::into_raw(ctx) as *mut c_void
}
#[no_mangle]
pub unsafe extern "C" fn insert_counter_context(context: *mut c_void, value: i32) {
let mut counter = Box::from_raw(context as *mut CounterContext);
counter.set.insert(value);
Box::into_raw(counter);
}
#[no_mangle]
pub unsafe extern "C" fn delete_counter_context(context: *mut c_void) {
let counter = Box::from_raw(context as *mut CounterContext);
for value in counter.set.iter() {
println!("counter value: {}", value)
}
}
internal static unsafe partial class NativeMethods
{
const string __DllName = "nativelib";
[DllImport(__DllName, EntryPoint = "create_counter_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void* create_counter_context();
[DllImport(__DllName, EntryPoint = "insert_counter_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void insert_counter_context(void* context, int value);
[DllImport(__DllName, EntryPoint = "delete_counter_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void delete_counter_context(void* context);
}
public class CounterContext
{
private void* _handle;
public CounterContext()
{
_handle = NativeMethods.create_counter_context();
}
public void Insert(int value)
{
NativeMethods.insert_counter_context(_handle, value);
}
~CounterContext()
{
NativeMethods.delete_counter_context(_handle);
}
}
This makes a more human-friendly experience.
I create tests for bindings in the same file with bindings themselves (or else it gets me a lot of troubles with visibility). And these test functions are includuded in bindings for C# so maybe don't include functions with #[test]
attribute? Or maybe even include only functions with #[no_mangle]
attribute? I can make pull request if this feature is needed.
When we have a struct field with an invalid name in C# world, it causes compilation failure.
For example:
pub struct NfcCard {
delegate: extern "C" fn(ByteArray) -> ByteArray,
}
This code is converted to:
[StructLayout(LayoutKind.Sequential)]
internal unsafe partial struct NfcCard
{
public delegate* unmanaged[Cdecl]<ByteArray, ByteArray> delegate;
}
In this context, the name delegate
is the reserved word in C#, so the compiler says:
error CS1519: Invalid token 'delegate' in class, record, struct, or interface member declaration
It would be great if csbindgen renames the reserved words of C# I think.
Simply run cargo test
cause following errors:
---- tests::update_package_version stdout ----
thread 'tests::update_package_version' panicked at 'index out of bounds: the len is 1 but the index is 1', csbindgen/src/lib.rs:185:12
note: run with RUST_BACKTRACE=1
environment variable to display a backtrace
---- tests::test stdout ----
starting dir: /Users/danielhu/Projects/csbindgen/csbindgen
thread 'tests::test' panicked at 'input file not found, path: csbindgen-tests/src/liblz4.rs: Os { code: 2, kind: NotFound, message: "No such file or directory" }', csbindgen/src/lib.rs:41:14
Hello, I am trying to understand what the NuGet csbindgen is used for as I am having troubles to understand this.
First of all, in Unity it would not be easy to install (nuGet is not supported there) but I am assuming this is just an utility (?). The whole CS bindings generation is done from Rust so I am a bit confused on why this is needed.
I tried to install such NuGet however from the IDE (which I know will be overwritten by Unity, but still it is to try it out) and I get:
Could not install package 'csbindgen 1.9.2'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.7.1', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.
However there is no clear dependency specified in csbindgen NuGet, so I am confused on why it does not work.
Can I solve this by simply adding the nuget code to my project somehow?
Hi, thanks for this awesome crate :)
I think *const char
should be translate to *const uint
.
0.1.2
I was getting *char
but I don't think this is acurate because sizeof(char) == 2
so the aligment might be also off1.4.0
I'm getting a *@char
not sure what is happeningout of scope on initial release but important to support.
https://doc.rust-lang.org/nomicon/ffi.html#the-nullable-pointer-optimization
https://qiita.com/termoshtt/items/7a610780e13d7dc62324
Can csbindgen look at a crates's dependencies when generating bindings? Let's imagine
Crate dll
:
pub use api_types::Vec2;
fn function(x: *const Vec2) {}
Crate types
:
#[repr(C)]
pub struct Vec2 {
pub x: f32,
pub y: f32,
}
Currently it looks like it doesn't search dependencies for types to output. If we run csbindgen in dll/build.rs
, it won't include types defined in types
.
That said, how can I integrate Rust's async
/await
with C#'s async
/await
.
#[repr(u8)]
pub enum FieldedEnum{
A(u8),
B(i8),
}
std::mem::size_of::<FieldedEnum>() -> 2
currently this gets translated as
public enum FieldedEnum : byte
{
A,
B
}
which is wrong in length
i am not sure if this is stabilized, but if the length of each field is the same i guess it may even now be considered okay to use.
https://doc.rust-lang.org/nomicon/other-reprs.html
i would suggest implementation like this:
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct MyData
{
public enum Variant : byte
{
A,
B
}
[StructLayout(LayoutKind.Explicit)]
private struct Union
{
[FieldOffset(0)]
internal byte A;
[FieldOffset(0)]
internal sbyte B;
}
public Variant Type { get; private set; }
private Union data;
public byte A
{
get
{
if (Type != Variant.A)
throw new InvalidOperationException($"{nameof(MyData)} is not of variant {nameof(Variant.A)}, but {this}");
return data.A;
}
set
{
Type = Variant.A;
data = new Union {A = value}; //must be done with with to make sure all other fields are zeroed out
}
}
public sbyte B
{
get
{
if (Type != Variant.B)
throw new InvalidOperationException($"{nameof(MyData)} is not of variant {nameof(Variant.B)}, but {this}");
return data.B;
}
set
{
Type = Variant.B;
data = new Union {B = value};
}
}
public override string ToString()
{
switch (Type)
{
case Variant.A:
return $"{nameof(MyData)}.{nameof(Variant.A)}: {A}";
case Variant.B:
return $"{nameof(MyData)}.{nameof(Variant.B)}: {B}";
default:
throw new InvalidOperationException("Invalid variant of {nameof(MyData)}!");
}
}
}
If there is a constant in the Rust file, it is not does not appear in the generated bindings.
pub const THINGY_CREATE_FLAGS__OPTIMIZE: u32 = 1 << 0;
For instance cbindgen makes this a #define
, if you target C.
#define THINGY_CREATE_FLAGS__OPTIMIZE (1 << 0)
I don't use Rust, so I'm not sure if I'm just setting up the files incorrectly, but I'm trying to take existing Rust code and call the functions from within C#.
I setup a submodule for the existing repo and then made a rslib-bridge folder to hold the csbindgen code.
Here are my files:
Cargo.toml
[package]
name = "rslib-bridge"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
[build-dependencies]
csbindgen = "1.8.0"
build.rs
fn main() {
csbindgen::Builder::default()
.input_bindgen_file("../anki/rslib/src/decks/service.rs")
.rust_file_header("use super::service::*;")
.csharp_entry_point_prefix("csbindgen_")
.csharp_dll_name("service")
.generate_to_file("service_ffi.rs", "../dotnet/NativeMethods.service.g.cs")
.unwrap();
}
This is the existing Rust file that I'm trying to generate from.
When I run cargo build
, I get the generated service_ffi.rs file, but it doesn't contain any of the function calls.
service_ffi.rs
/* automatically generated by csbindgen */
#[allow(unused)]
use ::std::os::raw::*;
use super::service::*;
I thought maybe it was because the service.rs file I'm pulling from uses impl
and has all the functions nested in it, instead of having them at the base level. So I deleted the generated files and tried again but this time using the default generated lib.rs file (with the test deleted) and got the same result.
src/lib.rs
pub fn add(left: usize, right: usize) -> usize {
left + right
}
build.rs
fn main() {
csbindgen::Builder::default()
.input_bindgen_file("src/lib.rs")
.rust_file_header("use super::service::*;")
.csharp_entry_point_prefix("csbindgen_")
.csharp_dll_name("service")
.generate_to_file("service_ffi.rs", "../dotnet/NativeMethods.service.g.cs")
.unwrap();
}
How can i generate bindings for structs with their corresponding impl functions?
Hi I am going crazy because something that seemed to be working doesn't really work anymore and I have no idea why.
I have a file:
src/classes/counter.rs
and its ffi:
src/ffi/counter_ffi.rs
I only run csbindgen on counter_ffi.rs and until last week it was also generating the empty structs for Counter and Args. But right now I cannot get it. I do not really know why and would need help, since this might be an issue.
Content of counter.rs:
#[repr(C)]
pub struct Args {
pub init: u32,
pub by: u32,
}
#[repr(C)]
pub struct Counter {
val: u32,
by: u32,
}
impl Counter {
pub fn new(args: Args) -> Counter {
Counter{
val: args.init,
by: args.by,
}
}
pub fn get(&self) -> u32 {
self.val
}
pub fn incr(&mut self) -> u32 {
self.val += self.by;
self.val
}
pub fn decr(&mut self) -> u32 {
self.val -= self.by;
self.val
}
}
Content of counter_ffi.rs:
use std::mem::transmute;
use crate::classes::counter::{Args, Counter};
#[no_mangle]
pub extern fn counterCreate(args: Args) -> *mut Counter {
let _counter = unsafe { transmute(Box::new(Counter::new(args))) };
_counter
}
#[no_mangle]
pub extern fn counterGetValue(ptr: *mut Counter) -> u32 {
let mut _counter = unsafe { &mut *ptr };
_counter.get()
}
The resulting .cs file DOES NOT contain the Counter struct, so the code is unusable. But I swear that it worked until now and I got the empty Counter struct there.
CS file:
internal static unsafe partial class CounterUnsafeFFI
{
[DllImport(__DllName, EntryPoint = "counterCreate", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Counter* counterCreate(Args args);
[DllImport(__DllName, EntryPoint = "counterGetValue", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern uint counterGetValue(Counter* ptr);
}
What am I missing? Really the counter_ffi.rs should be in the exact same file of the counter.rs?
I am using csbindgen
version 1.8.3
.
// GroupedNativeMethods.cs
using GroupedNativeMethodsGenerator;
namespace Bindings;
[GroupedNativeMethods]
internal static unsafe partial class Libsql{}
Here's one example of a generated extension method.
// Bindings.Libsql.GroupedNativeMethods.g.cs
...
public static bool RowsIteratorNext(this ref global::Bindings.RowsIterator @rows_iterator)
{
return Libsql.rows_iterator_next((global::Bindings.RowsIterator*)Unsafe.AsPointer(ref @rows_iterator));
}
...
According to the documentation, I'd expect RowsIterator
to be stripped and to have the extension method simply be Next
. Am I missing something obvious? Thanks.
My expectation was that running cargo build --release
would generate libzsd
and reference it from C#.
The build.rs
also has the following description.
csbindgen::Builder::new()
.input_bindgen_file("src/zstd.rs")
.method_filter(|x| x.starts_with("ZSTD_"))
.rust_file_header("use super::zstd::*;")
.csharp_class_name("LibZstd")
.csharp_dll_name("libzsd")
.generate_to_file("src/zstd_ffi.rs", ". /dotnet-sandbox/zstd_bindgen.cs")? ;
But I couldn't find libzsd
. The zstd_bindgen.cs
is generated without any problem.
I can't find the library specified in .csharp_dll_name
.
Sorry if my work is wrong.
I defined a struct in a crate:
#[repr(C)]
pub struct ByteVecPtr {
pub ptr: *const u8,
pub len: usize,
}
How to generate this struct to csharp when i dependency the struct . I can't find the .rs file when dependence on crate.io.
#[no_mangle]
pub extern "C" fn ads_read_motor_para_l(byte_vec_ptr:ByteVecPtr) -> bool {
return true;
}
Existing documentation generation seems to simply add summary
?
It does not convert rustdoc markdown syntax to C# doc syntax.
How about remove the summary, and I can directly write xml-style C# documents?
What is the best practice to convert rust Iterator to C# IEnumerator?
for example b3
B3_SHARED_API void b3GetUserDataInfo(b3PhysicsClientHandle physClient, int bodyUniqueId, int userDataIndex, const char** keyOut, int* userDataIdOut, int* linkIndexOut, int* visualShapeIndexOut);
const char** keyOut
-> *mut *const keyOut
Does it support framework 4.5.1?
I have to admit that this is not up to you to propose this but it is really sad that the .NET SDK doesn't offer a built-in way to retrieve native libraries. Or even providing a proper example on how to load native libraries.
Anyway, there is already a great solution in the readme that can work with win|osx|linux
OS and x86|x64|arm64
process architectures. However, it does not cover the full list of RIDs, or at least the most commonly used you can find here: https://learn.microsoft.com/en-us/dotnet/core/rid-catalog#known-rids
The current implementation is sufficient to cover Windows and OSX platforms. However, I do not find a way to cover Android and iOS platforms. And same for deduping musl vs. non-musl.
Did you encounter this issue and have you found a solution?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.