Restructure packaging directories. Move C# bindings, minor compilation fix.

This commit is contained in:
Joseph Henry
2021-02-01 17:59:21 -08:00
parent 3544eab41d
commit 38ea47212d
16 changed files with 106 additions and 71 deletions

View File

@@ -280,7 +280,7 @@ file (GLOB libminiupnpcSrcGlob
${ZTO_SRC_DIR}/ext/miniupnpc/upnpreplyparse.c)
if (ZTS_PINVOKE)
set (ZTS_SWIG_WRAPPER_FILE ${PROJ_DIR}/examples/csharp/*.cxx)
set (ZTS_SWIG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/csharp/*.cxx)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_PINVOKE=1")
endif ()
@@ -544,6 +544,8 @@ if (SHOULD_BUILD_TESTS)
target_link_libraries(nonblockingclient ${STATIC_LIB_NAME})
add_executable (nonblockingserver ${PROJ_DIR}/examples/cpp/nonblockingserver.cpp)
target_link_libraries(nonblockingserver ${STATIC_LIB_NAME})
add_executable (keymanagement ${PROJ_DIR}/examples/cpp/keymanagement.cpp)
target_link_libraries(keymanagement ${STATIC_LIB_NAME})
if (CENTRAL_API)
add_executable (centralapi ${PROJ_DIR}/examples/cpp/centralapi.cpp)
target_link_libraries(centralapi ${STATIC_LIB_NAME})

View File

@@ -1,5 +1,46 @@
function CreateNugetPackage
{
md builds\pkg\nuget -Force
# runtimes
md pkg\nuget\ZeroTier.Sockets\runtimes\win10-x86\native -Force
md pkg\nuget\ZeroTier.Sockets\runtimes\win10-x64\native -Force
md pkg\nuget\ZeroTier.Sockets\runtimes\win10-x64\lib\uap10.0 -Force
md pkg\nuget\ZeroTier.Sockets\runtimes\win10-arm\native -Force
# frameworks
md pkg\nuget\ZeroTier.Sockets\lib\net48 -Force
md pkg\nuget\ZeroTier.Sockets\lib\net5.0 -Force
# Build native libzt with exported P/INVOKE symbols
Build-Library -BuildType "Release" -Arch "x64" -LanguageBinding "csharp"
Build-Library -BuildType "Release" -Arch "x64" -LanguageBinding ""
Build-Library -BuildType "Release" -Arch "Win32" -LanguageBinding "csharp"
#Build-Library -BuildType "Release" -Arch "ARM" -LanguageBinding "csharp"
# Copy assemblies into NuGet package tree
Copy-Item .\lib\release\win-x64-pinvoke\*.dll pkg\nuget\ZeroTier.Sockets\runtimes\win10-x64\lib\uap10.0\libzt.dll
Copy-Item .\lib\release\win-x64\*.dll pkg\nuget\ZeroTier.Sockets\runtimes\win10-x64\native\libzt.dll
Copy-Item .\lib\release\win-x86-pinvoke\*.dll pkg\nuget\ZeroTier.Sockets\runtimes\win10-x86\native\libzt.dll
#Copy-Item .\lib\release\win-arm-pinvoke\*.dll pkg\nuget\ZeroTier.Sockets\runtimes\win10-arm\native\libzt.dll
# Build wrapper library for C# ZeroTier.Sockets abstraction
csc -target:library -out:pkg\nuget\ZeroTier.Sockets\lib\net5.0\ZeroTier.Sockets.dll .\src\bindings\csharp\*.cs
# Package everything
Push-Location -Path pkg\nuget\ZeroTier.Sockets
del ZeroTier.Sockets.*.nupkg
nuget pack ZeroTier.Sockets.nuspec -OutputDirectory ..\..\..\builds\pkg\nuget
Pop-Location
}
function Clean
{
Remove-Item builds -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue'
Remove-Item tmp -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue'
Remove-Item lib -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue'
Remove-Item bin -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue'
@@ -29,11 +70,11 @@ function Build-Library([string]$BuildType, [string]$Arch, [string]$LanguageBindi
$bitCount="64"
$archAlias="win-x64"
}
if ($Arch -eq "ARM32") {
$bitCount="32"
$archAlias="win-arm"
}
if ($Arch -eq "ARM64") {
#if ($Arch -eq "ARM32") {
# $bitCount="32"
# $archAlias="win-arm"
#}
if ($Arch -eq "ARM") {
$bitCount="64"
$archAlias="win-arm64"
}

View File

@@ -1,12 +0,0 @@
debug:
cd ../../ && make host_pinvoke_debug
cp -f ../../lib/debug/linux-x86_64/libzt.so .
mono-csc -out:example.exe *.cs
release:
cd ../../ && make host_pinvoke_release
cp -f ../../lib/release/linux-x86_64/libzt.so .
mono-csc -out:example.exe *.cs
clean:
rm -rf libzt.* example.exe

View File

@@ -1,22 +1,28 @@
ZeroTier Sockets for C# .NET (Work In Progress)
ZeroTier Sockets for C# .NET
=====
This library is a re-implementation of the .NET socket class ([System.Net.Sockets.Socket](https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket)) built atop ZeroTier's SDK using P/INVOKE and is designed to be a direct drop-in replacement. The library consists of three main objects: `ZeroTier.Node`, `ZeroTier.Event`, and `ZeroTier.Socket`. No code change is required in your application beyond a small snippet of startup code, renaming `Socket` to `ZeroTier.Socket` (where applicable) and handling a smattering of events.
A replacement for the [System.Net.Sockets.Socket](https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket) class built atop ZeroTier's SDK using P/INVOKE. It is designed to be a direct drop-in replacement. The library consists of three main objects: `ZeroTier.Node`, `ZeroTier.Event`, and `ZeroTier.Socket`. No code change is required in your application beyond a small snippet of startup code, renaming `Socket` to `ZeroTier.Socket` (where applicable) and handling a smattering of events.
# Overview
tl;dr:
Add `ZeroTier.Sockets` to your project:
```powershell
Install-Package ZeroTier.Sockets
```
See [example.cs](./example.cs) for complete client/server app implementation.
```csharp
using System.Net.Sockets;
using ZeroTier;
void myCallback(ZeroTier.Event e)
void OnZeroTierEvent(ZeroTier.Event e)
{
Console.WriteLine("{0} ({1})", e.EventCode, e.EventName);
}
...
ZeroTier.Node node = new ZeroTier.Node("path", myCallback, 9991);
ZeroTier.Node node = new ZeroTier.Node("path", OnZeroTierEvent, 9991);
node.Start();
node.Join(0xc287ac0b42a6fb4c);
@@ -31,15 +37,28 @@ sock.Connect(remoteEndPoint);
node.Stop();
```
See [example.cs](./example.cs) for a complete client/server implementation.
## Building and running the example
# Building example without NuGet package (Advanced)
From top-level repo directory, build `libzt.dll/so/dylib`:
```bash
make host_pinvoke_release
```
Copy `libzt.dll/so/dylib` into this project directory:
```
make debug|release
cp ../../lib/release/${YOUR_HOST_TUPLE}-pinvoke/libzt.* .
```
Where `${YOUR_HOST_TUPLE}` is something like: `linux-x86_64`, `macOS-x86_64`, etc.
Build language binding layer, `ZeroTier.Sockets.dll`:
```bash
cd examples/csharp
${CSHARP_COMPILER} -target:library -out:ZeroTier.Sockets.dll ../../src/bindings/csharp/*.cs
${CSHARP_COMPILER} -reference:ZeroTier.Sockets.dll example.cs
./example.exe
```
## Development notes
The SWIG interface file `zt.i` is only present for historical reference purposes. SWIG generates a ton of unnecessary boilerplate code which is hard to completely prevent using hints. You can generate a new wrapper for yourself using `swig -c++ -csharp -dllimport "./libzt.so" zt.i` but I would not recommend doing so unless you know what you're in for.
Where `${CSHARP_COMPILER}` may be `csc` or `mono-csc` depending on your platform.

View File

@@ -39,6 +39,11 @@
extern "C" {
#endif
#ifdef ZTS_PINVOKE
// Used by P/INVOKE wrappers
typedef void (*CppCallback)(void *msg);
#endif
//////////////////////////////////////////////////////////////////////////////
// Event codes //
//////////////////////////////////////////////////////////////////////////////
@@ -1096,8 +1101,6 @@ ZTS_API int ZTCALL zts_disable_local_storage(uint8_t disabled);
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE or ZTS_ERR_ARG on failure
*/
#ifdef ZTS_PINVOKE
// Used by P/INVOKE wrappers
typedef void (*CppCallback)(void *msg);
ZTS_API int ZTCALL zts_start(const char *path, CppCallback callback, uint16_t port);
#else
ZTS_API int ZTCALL zts_start(const char *path, void (*callback)(void *), uint16_t port);

View File

@@ -1,30 +0,0 @@
/* libzt.i */
%begin
%{
#define SWIG_PYTHON_CAST_MODE
%}
%include <stdint.i>
#define PYTHON_BUILD 1
%module libzt
%{
#include "../include/ZeroTier.h"
#include "../include/ZeroTierConstants.h"
%}
%define %cs_callback(TYPE, CSTYPE)
%typemap(ctype) TYPE, TYPE& "void *"
%typemap(in) TYPE %{ $1 = ($1_type)$input; %}
%typemap(in) TYPE& %{ $1 = ($1_type)&$input; %}
%typemap(imtype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(cstype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(csin) TYPE, TYPE& "$csinput"
%enddef
%cs_callback(userCallbackFunc, CSharpCallback)
%include "../include/ZeroTier.h"
%include "../include/ZeroTierConstants.h"

4
src/README.md Normal file
View File

@@ -0,0 +1,4 @@
# C++ Source
- C API is exposed via [include/ZeroTierSockets.h](./../include/ZeroTierSocket.h)
- [bindings/](./bindings) Contains the source for wrappers in various languages. See [examples/](./../examples) for their usage.

4
src/bindings/README.md Normal file
View File

@@ -0,0 +1,4 @@
# Language Bindings
These subdirectories contain the abstraction implementations for using libzt in an idiomatic way for languages other than C\C++. Packages which may draw upon these sources are found in [pkg/](../../pkg). Example usage of these bindings can be found in [examples/](../../examples).

View File

@@ -204,10 +204,10 @@ namespace ZeroTier
public Node(string configFilePath, ZeroTierManagedEventCallback managedCallback, UInt16 servicePort)
{
if (String.IsNullOrEmpty(configFilePath)) {
throw new ArgumentNullException(nameof(configFilePath));
throw new ArgumentNullException("configFilePath");
}
if (managedCallback == null) {
throw new ArgumentNullException(nameof(managedCallback));
throw new ArgumentNullException("managedCallback");
}
_nodeId = 0x0;
_configFilePath = configFilePath;

View File

@@ -0,0 +1,4 @@
# C# Language Bindings
- Install (via [NuGet package](https://www.nuget.org/packages/ZeroTier.Sockets/)): `Install-Package ZeroTier.Sockets`
- Example usage: [examples/csharp](./../../../examples/csharp/)

View File

@@ -135,7 +135,7 @@ namespace ZeroTier
throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
}
if (remoteEndPoint == null) {
throw new ArgumentNullException(nameof(remoteEndPoint));
throw new ArgumentNullException("remoteEndPoint");
}
int err = Constants.ERR_OK;
int addrlen = 0;
@@ -194,7 +194,7 @@ namespace ZeroTier
throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
}
if (localEndPoint == null) {
throw new ArgumentNullException(nameof(localEndPoint));
throw new ArgumentNullException("localEndPoint");
}
int err = Constants.ERR_OK;
int addrlen = 0;
@@ -412,7 +412,7 @@ namespace ZeroTier
throw new ZeroTier.SocketException((int)ZeroTier.Constants.ERR_SOCKET);
}
if (buffer == null) {
throw new ArgumentNullException(nameof(buffer));
throw new ArgumentNullException("buffer");
}
int flags = 0;
IntPtr bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
@@ -428,7 +428,7 @@ namespace ZeroTier
throw new ZeroTier.SocketException((int)ZeroTier.Constants.ERR_SOCKET);
}
if (buffer == null) {
throw new ArgumentNullException(nameof(buffer));
throw new ArgumentNullException("buffer");
}
int flags = 0;
IntPtr bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);

View File

@@ -30,9 +30,9 @@ namespace ZeroTier
SocketErrorCode = _socketErrorCode;
}
/// <value>High-level service error code. See Constants.cs</value>
public int ServiceErrorCode { get; }
public int ServiceErrorCode { get; private set; }
/// <value>Low-level socket error code. See Constants.cs</value>
public int SocketErrorCode { get; }
public int SocketErrorCode { get; private set; }
}
}