Git Product home page Git Product logo

gir.core's Introduction

Welcome to Gir.Core

Continuous integration status Website depolyment status

Gir.Core provides C# bindings for several GObject based libraries like GTK for user interfaces.

This project aims to provide a complete set of APIs for writing rich cross-platform user interfaces and multimedia programs. It is built upon the well-established GObject Introspection framework for language bindings.

Features

  • Idiomatic C#: An API which feels natural to C# developers (including the async/await feature).
  • Simplicity: Memory management is handled automatically, greatly simplifying the C-API.
  • Complete API: Support for the entire GTK and GStreamer stack, enabling feature-rich applications which deeply integrate with the OS.
  • Extensibility: Allows 3rd party developers to write bindings for other GObject-based libraries, achieving full interoperability between them.

Status

The code is under development and not ready for production use. There are nuget packages available. The API is subject to change as long as version 1.0 is not released. Feel free to visit the nuget organization to get an overview.

The upcoming features and releases can be checked out in the milestones.

Supported Libraries

Library Description Level of Support
GTK-4.0 UI-Toolkit Partial
Libadwaita-1 Building blocks for modern GNOME applications Partial
GStreamer-1.0 Multimedia Framework Partial
Cairo-1.0 Graphics Library Partial
Pango-1.0 Font/Text Library Partial
Gio-2.0 Library for high level application functionality Partial
GdkPixbuf-2.0 Image loading in various formats Partial
libshumate Library to display maps Planned
WebKit-6.0 Browser engine (Linux only) Partial
JavaScriptCore-6.0 JavaScript engine for WebKit (Linux only) Partial
GtkSource-5 Extends a Gtk.TextView to be like a source code editor Partial

Get Involved

Anyone who wants to help is very welcome. If you want to get in contact feel free to chat with us via matrix (#gircore:matrix.org) or open a discussion and don't forget to check out our contribution guidelines.

Build

To generate the bindings locally execute the following commands in a terminal. Make sure to initialise submodules with --recursive otherwise the gir-files directory will not be loaded properly.

$ git clone --recursive https://github.com/gircore/gir.core.git
$ cd gir.core/src
$ dotnet fsi GenerateLibs.fsx
$ dotnet build GirCore.Libs.slnf

If you want to clean the Libs folder of all generated files run:

$ dotnet fsi CleanLibs.fsx

For more advanced build options, see the documentation.

Code structure

The folder structure in this repository is organized as follows:

The code in the library folder is not complete because most of the code is generated when the GirTool is run.

Licensing terms

Gir.Core is licensed under the terms of the MIT-License. Please see the license file for further information.

The Gir.Core logo is built upon the original GTK logo by Andreas Nilsson which is licensed under the GNU Free Documentation License and was relicensed under CC BY-SA 3.0. Therefore the Gir.Core logo is licensed under the CC BY-SA 3.0, too.

gir.core's People

Contributors

badcel avatar blquinn avatar cameronwhite avatar dependabot[bot] avatar firox263 avatar fleimeris avatar fogzot avatar fsobolev avatar github-actions[bot] avatar hhyyrylainen avatar hol430 avatar kant2002 avatar kashifsoofi avatar knuxbbs avatar mikkeljohnsen avatar mjakeman avatar na2axl avatar nlogozzo avatar ultimaweapon avatar urtsisantsi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gir.core's Issues

Unit test names are to long

The names of unit test methods are to long and the context is hard to grasp. We should work out some convention which we can apply to our unit tests which sattisfy our needs of simplicity and readability.

Virtual Method support

I had a small break through today regarding virtual methods and overriding thank's to the help of @webczat in gitter/chsharplang.

What do you think of the virtual method implementation in https://github.com/gircore/gir.core/tree/spike/virtual_methods ?

The code would would probably not stay like this from an public API point of view. But the executed calls would if you agree with this this attempt in general.

It does not integrate virtual methods in the original objects like Button, but there could be some code generated for subclasses to get this done via an attribute like shown in the branch. In this way we do not sacrifice on the performance if there is nothing overloaded.

I placed the Button subclass just at the end of the Quickstart program:

public class MyButton : Button

Could you test the code on windows, too @gircore/coreteam ?

Gracefully handle exceptions in the Build Tool

Currently, if the build tool fails for whatever reason, it prints out the exception followed by a long stack trace. We should handle common failures gracefully and print out a helpful error message rather than >50 lines of stderr.

Particularly:

  • GIR files cannot be found -> Instruct the user to pull the most up to date version of gir-files (and/or init submodules)
  • Generation failure -> Print relevant inner exceptions only, rather than all of the threading-related exceptions Bullseye generates on failure. Could direct the user here to open an issue.

Project structure (Core / Wrapper)

I've seen that the way we are separating projects now (Name.Core and Name.Wrapper) give us some limitations (by @na2axl)

I think our current arrangement is not intentional as such, but rather because we just built on top of what was already there (initially we had pure ABI structs in Name.Wrapper, hence the strange split)

In my opinion, we should keep the wrapper entirely auto-generated and move Sys.Value, etc to the Core namespace (we're already doing this with Sys.Type -> GObject.Type). This way, we get around any limitations while still keeping the nice separation between unmanaged functions and our 'safe' API.

Originally posted by @firox263 in #67 (comment)

GObject struct generation: Methods are public

The generated methods for structs are all public and not part of a protected static class Native. This class should be generated to hide the low level access in the same way like it is done for classes.

GInterface properties

Hello @badcel, @firox263 ,

I think we have to review the way to handle GInterface properties. I'm currently working on the widget catalog samples, I'm seeing that for now the generator is creating empty GInterfaces. I think we can at least generate an inner Native class which will contain the list of property names of that interface, so for example in the Box class we will have:

public static readonly Property<Orientation> OrientationProperty = Property<Orientation>.Register<Box>(
    Orientable.Native.OrientationProperty,
    nameof(Orientation),
    (o) => o.Orientation,
    (o, v) => o.Orientation = v
);

Also, since the Orientable interface for example can be used by many classes, I think it will be better to have the property descriptor in the interface, but not the properties.

public partial interface Orientable
{
    #region Properties

    public static readonly Property<Orientation> OrientationProperty = Property<Orientation>.Register<Orientable>(
        Native.OrientationProperty,
        nameof(Orientation),
        (o) => o.Orientation,
        (o, v) => o.Orientation = v
    );

    Orientation Orientation { get; set; }

    #endregion

    #region Native

    public static class Native
    {
        public const string OrientationProperty = "orientation";
    }

    #endregion
}

So in the implementations like Box we have:

public partial class Box : Orientable
{
    public Orientation Orientation
    {
        get => GetProperty(Orientable.OrientationProperty);
        set => SetProperty(Orientable.OrientationProperty, value);
    }
}

Like that we will not rewrite property descriptors in every implementations (what seems strange for me...).

What do you think ?

[RFC002] Static GProperty Descriptors

Static GProperty Descriptors

RFC

Please see the RFC here: https://github.com/gircore/rfcs/blob/master/rfc-002-static-properties.md
It explains the proposal and some potential solutions.

Summary

To allow Gir.Core be a part of the current C# UI ecosystem, the implementation of GProperties can be done using Static Properties, to match what it's done now using DependencyProperty in other libraries. For that we have the following goals:

  • Declare GProperties of current Wrappers using Static Properties;
  • Allow library users to declare GProperties of theirs Subclass using Static Properties;
  • An high-level API will provide access to the GProperty value, to retrieve and edit it through the corresponding Property Descriptor.
  • Property Descriptors must know the type (the C# type) of the GProperty;
  • Property Descriptors must know the type (the C# type) of the GObject in which it will be registered;
  • Property Descriptors must know the name of the GProperty;
  • Property Descriptors must know if the GProperty is write-only, read-only, or read-write;
  • Property Descriptors must allow an easy registration and initialization of the GProperty in the GObject;
  • Property Descriptors must also describe child GProperties;
  • All of these points must be implemented in an easy to use, DependencyProperty-like manner.

These goals can lead us to these achievements:

  • Type System Integration with GObject, as discussed in #46, and described by [RFC001].
  • Solid MVVM binding model, as discussed in #34, and described by [RFC003].

Update libhandy

libhandy has released the first beta of the final API. The API is marked stable.

Update libhandy to a version >= 0.90.0 as soon as it is available as a package.

Documentation

As we settle more and more on specific decisions how to progress, there is some need to document this project for our self and potential users.

From my point of view there are 3 kinds of documentation needed:

  • API documentation: Which APIs are available?
  • Developer documentation: How does everything work?
  • User documentation: How to use the libraries?

We have several possibilities on how / where to document and should find a solution we want to stick with to avoid moving the documentation around:

  • Github Readme
  • gircore/gir.core repository with a folder named "Documentation": I saw this lately on some projects. In this case the documentation is part of the code and is tagged with releases, etc.
  • Separate repository (RFC): Much space for comprehensive documentation
  • Homepage (is generated automatically from github repository with markdown). Is able to generate API documentation
  • Github wiki

I want as less dobuled documentation as possible. Even know I don't like the duplication between the github readme and the homepage. The homepage is already out of date.

Are there any preferences or suggestions or missing things?

Cache Fallback Lookups in Typedict

If we lookup 'GdkWin32Screen' in the typedict, since we don't provide bindings for Gdk's private API, we instead fallback to the next-best type of GdkScreen (as intended).

However, we only cache GdkScreen <-> Gdk.Screen and not GdkWin32Screen <-> Gdk.Screen, meaning that every time we do this lookup again, we go through the more expensive assembly search, rather than simply returning from the dictionary.

We should cache not only resolved types, but also ones that intentionally fail to resolve, to avoid unnecessary work.

This is particularly relevant for GStreamer, as we do this lookup every time we create an Element.

Closures Handling

As discussed in #103, this issue is to find a solution about closures handling in Gir.Core libraries.
This issue can be related to #109


@firox263: Borrowing this to add a TODO

TODO 6/05/21:

  • Reimplement Native->Managed marshalling (so we can call the user's provided delegate)
  • Properly exclude certain parameters like userData
  • Write unit/integration tests

Completed:

  • Prototype Notified
  • Prototype Async
  • Prototype Default/Call
  • Generator should use Native-suffix in native function calls
  • Generator needs a way to marshal any arbitrary type from Native->Managed (this may require the generator rewrite to achieve?)
  • Come to a decision whether DestroyNotify is useful in the end user API
  • Implement Notify in Generator
  • Implement Async in Generator
  • Implement Call in Generator
  • Fix DBusConnection and a few existing uses
  • Memory Leak Testing

Move GObject / GLib into Runtime folder

Move GObject / GLib into a new Runtime folder.

The code in GObject / GLib will be mostly written by hand as it is the foundation code to allow bindings and acts as some kind of runtime.

The remaining projects int he Libs folder will be as much autogenerated as possible.

This depends on #134 as there are some cleanups regarding csproj files which allow to avoid duplicated csproj code (General.props and Nuget.props).

Generator rewrite

If the generator is rewritten the following features should be thought of:

  • Prefixing of interfaces (requires loading of other libraries while one library is generated, to detect if a type is an interface)
  • Generation of properties which are defined in an interface (requires loading of a different XML than the one which is currently generated)

Non-object memory management

We need to free memory appropriately for structs and disguised structs ("structs as classes").

GStreamer defines a "free function", but does not have an attribute for this.

Unsafe vs IntPtr

Hey there,

Since we are planning to use .NET 5 and function pointers, isn't right to also use unsafe contexts on some other points of the code ? I'm asking especially for structs, to use things like GLib.List* instead of an IntPtr. I think like that we will avoid a lot of marshaling/unmarshaling (which is an issue I'm facing while working on #103.

The unsafe context will only be used for Native classes, we will wrap them and provide safe contexts to end users through the high level API.

Any thoughts @badcel, @firox263 ?

Spacing problems with Scriban

...

There's still a problem with spacing between each field being wildly inconsistent, not really sure how to go about fixing that.

Originally posted by @firox263 in #127 (comment)

๐Ÿ‘ Those vertical white space problems have s.th. to do with the documentation if it is generated / available or not. It is happening for fields in structs, too (but with one line less in between...).

It's not very nice but probably involves some update to Scriban. I did not take the time to reproduce the exact steps involved in it as the behavior is probably intended but not usefull for our case. So we would need to create some minimal samples and explain why it is bad for us and make some suggestions on how to improve it to the scriban project.

[RFC-1] Type System Integration with GObject

Integrating C# and GObject

RFC

Please see the RFC here: https://github.com/gircore/rfcs/blob/master/rfc-001-type-integration.md
It explains the proposal and some potential solutions.

Summary

Type Integration means that when the user creates a class that derives from GObject.Object, the library will automatically create a corresponding GType behind the scenes. Effectively, it allows us to write "native" GObject code using C#.

This enables us to implement the following features, among many others:

  • GObject Properties - Subclasses can expose properties to the gobject type system, allowing for them to be viewable/changeable in GtkInspector, etc.
  • Overriding Virtual Functions - Subclasses can override virtual functions (See GtkWidgetClass). For example, creating a custom container widget in Gtk with full control over sizing and layout.
  • Composite Template Support - Supports binding a subclass to a composite template defined in an XML file. Particularly useful for complex custom widgets.
  • Bidirectional Bindings - The possibility of using C# defined types from C and/or other language bindings. With .NET 5 we can use source generators to output native-callable functions.

Like with the namespace refactor (#27, PR #45), this will be a huge change that affects almost the entire codebase. For this reason, it is probably best to focus on completing this before we write more bindings.

Contribution

@badcel, I am very intrigued by this project and it's goals. I too would like to see libhandy brought to .NET to help bring .NET Core to mobile devices (eg. smartphones) and responsive interfaces on desktops.

I saw your open invitation for contributors on issue 144 of GtkSharp and examined the projects current progress and have to say this is a very exciting project.

Is there an area where you would prefer to see contributions in this endeavor?

Apply editor config code style

The editorconfig code style is not consistently applied to the code base. It must be worked through the code files and be applied.

Typedict expensive lookup

A thought:

We should probably check if the GType of generic type 'T' is equal to the gtype from the pointer. That way, we can avoid the expensive lookup in the type dictionary for cases where we know the type we want (e.g. Dialog.GetContentArea).

Originally posted by @firox263 in #65 (comment)


I created an issue so we don't forget about this comment. I currently don't see the expensive lookup. Perhaps you could just create a pull request?

Building on Windows

Ideally, gir.core should be able to work 'out of the box' on Windows.

Building
I've managed to get the project building (see #37). This involves remapping shared library names to dll names in order to link with the proper libraries.

GTK Binaries
GTK Binaries must be installed manually at the moment. I am using the MSYS2 binaries since they are the recommended way to get GTK on Windows (from the website).

To link with the native libraries, I added a function that remaps the shared library name to the DLL name. This is problematic as MSYS2 and vcpkg use different DLL names (libglib-2-0.dll vs glib-2.dll). It looks like vcpkg might be updating their GTK builds to use meson directly, so hopefully this will be fixed.

Missing Libraries
There are a few other issues remaining, most notably that webkit2gtk doesn't build on Windows anymore (see PR for info). We might need some way of marking a lib as platform specific, so we don't unnecessarily generate wrappers.

Feedback is very much appreciated.

Remove implicit casts from Object

Remove implicit casts from Object: This increases readability.

public static implicit operator IntPtr (Object? val);
public static implicit operator Object? (IntPtr val);

Support GStreamer (Gst Plugins)

We should support using GStreamer with Plugins (as base GStreamer isn't all that useful). I think it's best we get this working ahead of any generator rewrite, since GStreamer uses GObject directly.

  • GStreamer plugins have individual gir metadata files (see gstreamer-rs/gir-files).
  • It would make sense to namespace plugins under Gst, for example GstAudio -> Gst.Audio.
    • I'm not sure if we can infer this from gir data?
  • Parts of GStreamer rely on first-class interface support, so this will include #110 and #104.
  • Outside of Gtk, GStreamer is the other big client of GObject, so there'll be intricacies to work around.
    • While typed properties (via property descriptors) are great and should be used whereever possible, GStreamer relies on being able to retrieve properties from string representations too.
  • Easy GStreamer <-> Gtk interop for writing media-enabled applications.

Considerations:

  • Investigate controlled properties?
  • Allow for access to public struct member data (in the case of GstObject->flags)
  • Fix clash in generator between capitalisation and reserved keywords (e.g. null->@null, whereas it should be null->Null, see Gst.State).

Full Interface Support

While trying to implement TreeSelection, I ran into an issue where I needed to get a GObject of some (theoretically) unknown type and return it as an interface. We should make Try/WrapPointerAs support returning interfaces as well as objects.

After #102, I think interfaces are the only "big thing" left in terms of type integration before we've covered most of the GObject type system. Let's use this to track interface support.

To Do:

  • Support interface properties (#104)
  • Support interfaces in Try/WrapPointerAs
  • Allow user to implement GInterfaces for their subclasses
    • This will need to be done during type registration for GObject to recognise it

Future:

  • Allow the user to export custom C# interfaces as GInterfaces?
    • Would be similar to object registration
  • Prefix interfaces with I for consistency
    • Would be done alongside the generator rewrite

Cache DLLs in DllImport

Investigate whether we can/should cache the resolved DLL between calls to avoid a lookup each time we call a native method.

From #154:

na2axl: Maybe a way to cache the loaded library, to avoid redundant loading ?

badcel: I'm not sure if there is some caching on the side of NativeLibrary.TryLoad.
This reads a little bit like it: docs.
If you agreee I would avoid adding caching for now. If we see problems later or have definitive feedback that we are missing an opportunity here we can add the caching ourself.
gircore/coreteam what do you think?

badcel: Hm I added a Console.WriteLine and the ImportResolver method is called several times. So it looks like it is not caching. But I'm not sure if we should add caching and if this could result in some unexpected results.
Edit: I found no search results which did some caching. Perhaps there are multiple contexts involved and multiple calls are correct?

na2axl: I think we can check that by printing the returned IntPtr to the console, if the result is the same may be it's finally better to cache ?
But I've no problem to skip this for now.

Object IntPtr constructor

From what I recall, the this(Native.@new) pattern breaks when subclassing, as we need to be going through either Object() or Object(ConstructParameter[]) for the type integration code to run. The IntPtr constructor would simply wrap the GtkApplication as a foreign-created object.

Originally posted by @firox263 in #95 (comment)

Are you sure about this? Can't we just add the type dictionary integration to the Object(IntPtr) constructor, too?

Generation of global functions

Currently all global functions are public. Probably each function has some class where it could part of as a public static method.

Do we want to make the global class internal and call the global functions only from inside our library?

Alternatively we keep the global class public. In this case we should probably put the methods into a protected static Native class because the method signatures are full of IntPtr parameters. Then we could try to generate methods with a user friendly signature to access the native functions.

Create a WidgetCatalog sample

The WidgetCatalog will showcase the usage of every widgets in GTK3 (WidgetCatalog3) and GTK4 (WidgetCatalog4) with Gir.Core. This kind of sample is the first one experienced developers and newbies search when browsing a new UI framework.

Code style

We should define a code style we all agree on to avoid later discussion and ensure a consistent code base for gir.core This could be an RFC.

Type Dictionary Tracking Issue

Found a really nasty bug with the type dictionary in our lookup code. If we don't instantiate an object before using it in WrapPointerAs<T>, it instead falls back (as intended) to the 'lowest common denominator' type. This is needed for Gdk objects, as a GdkScreen is actually a GdkWin32Screen (but of course, that's an internal type which is not exposed to bindings), so we default to GdkScreen instead.

The problem however, is we end up falling back to the last registered type, which in most cases ends up being either Gtk.Widget or a plain GObject. This always causes an Exception when used with WrapPointerAs<T> since you can't cast a true GObject type up to a Gdk.Screen for example.

Since this basically involves rewriting half the typedict, I've decided to do it all in one go and fix some of the other issues we had in the process. I'm currently working on this at firox263->feature/typedict.

TODO:

  • Rewrite lookup code to search registered and non-registered types.
  • Handle Unloaded Assemblies (e.g. Cairo, Pango, etc) Anti-Feature -> No Longer Considered
  • Find a better way of obtaining the Namespace vs the Type Name from GObject (Currently it just takes the first "word" so GtkTextView -> Gtk + TextView. This is problematic with things like GtkSourceView where it doesn't fall under the Gtk assembly but does under the namespace).
  • Do a check with TypeDescriptors to be sure the objects are derived.
  • More robust handling of full type names. Assembly.GetType(string) needs the type name in the form Namespace.Type, so maybe each assembly should define some kind of metadata with the namespace it implements.
  • Register recursively up the entire tree where possible, as this is much cheaper than doing it later.
  • Optimise this with a few "fast paths" to avoid doing expensive lookups. This fixes #66
  • Investigate more optimisations

Garbage Collection frees needed objects

We have several instances where delegates and callbacks get garbage collected when the computer is low on RAM. A typical error message looks something like this:

Process terminated. A callback was made on a garbage collected delegate of type 'GObject!GObject.WeakNotify::Invoke'.
   at Gtk.Global.main()
   at Gtk.Global.main()
   at Gtk.Global.Main()
   at GtkDemo.Program.Main(System.String[])

Once #52 is merged, I will try look into this along with some other changes to lifecycle code (e.g. ToggleRefs), so not very pressing at the moment.

Namespaces and class names

The current class names of the high level classes are mostly prefixed with a "G" to avoid conflicts with the generated class for the low level api.

The namespace is "[Library].Core". The low level classes live in the namespace "[Library]".

Should the high level namespace be part of the low level namespace? I would like to separate the layers completely, allowing simpler class names and clean namespaces.

Should there be one global namespace for the high level api or should every library be on its on namespace? How would theses namespaces be named?

Feel free to post your opinion.

New release process

  • Add the gir version to the package id (see #669 )
  • Specify version number via directory build props
  • Manually create releases via github workflow

Old:

  • Should the version number be part of the code to allow "reproduceable" builds or be taken from a release tag?
  • Should we take the version numbers from all of the projects individually? (GTK / GObject / Generator global tool / ...)?
  • Do we just take the major version number of each project and add our own afterwards (the gir is not more specific than this)?
  • Do we use our own version numbers completely and add the version of the GIR file into the package name, (like the *.so filename)? In this way each new major version of a library would be a new nuget and could be supported individually. (Preferred)
  • Should the GirTool be released independently from the generated projects? (yes, as a global tool)
  • Do we need to be able to update the libs independently from current develop branch? It would be simpler if not then we could always release from develop and rename develop to main.

Nuget Package

It would be awesome to have a nuget package bundled up.

I'm keen to find a start creating c# apps for the Linux desktop/mobile software ecosystem, and I think this would go a long way.

Toolkit layer / Higher level C# integration

This is a collection of ideas which could lead to better integration of this library into thje C# eco system. Those ideas are low on the priority list, as long as we are working on the basics of gir.core.

  • Gio.SimpleAction: It should be able to create an action which is supporting the ICommandinterface

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.