SwissEphSharp 2.10.3.1
dotnet add package SwissEphSharp --version 2.10.3.1
NuGet\Install-Package SwissEphSharp -Version 2.10.3.1
<PackageReference Include="SwissEphSharp" Version="2.10.3.1" />
<PackageVersion Include="SwissEphSharp" Version="2.10.3.1" />
<PackageReference Include="SwissEphSharp" />
paket add SwissEphSharp --version 2.10.3.1
#r "nuget: SwissEphSharp, 2.10.3.1"
#:package SwissEphSharp@2.10.3.1
#addin nuget:?package=SwissEphSharp&version=2.10.3.1
#tool nuget:?package=SwissEphSharp&version=2.10.3.1
SwissEphSharp
A C# port of the Astrodienst Swiss Ephemeris, the astronomical library used to compute planetary positions, house cusps, eclipses and related quantities. It is a line-by-line translation of Astrodienst's C source rather than a reimplementation, so the function names, arguments and return values are the ones in Astrodienst's own programming documentation.
swe_version() reports 2.10.03. Targets netstandard2.0, net8.0 and net10.0. No
dependencies.
Read the license first
Swiss Ephemeris, and therefore this library, is dual-licensed, and one of the two options has a condition that catches people out. You must choose one:
- AGPL-3.0. Free, but with a network clause. If you run this library as part of a service that users reach over a network, a web app, an API, a SaaS product, the AGPL requires you to offer those users the complete corresponding source of your whole service, not just this library. Operating the service is the trigger; you do not have to distribute a binary to anyone. If that does not work for your project, AGPL is not your option.
- Swiss Ephemeris Professional License. A commercial license bought from Astrodienst, without the source-disclosure obligation.
This is not a choice this package makes for you, and it follows Astrodienst's own relicensing of
Swiss Ephemeris. LICENSE, agpl-3.0.txt and NOTICE ship at the root of this package.
Install
dotnet add package SwissEphSharp
The package ID is SwissEphSharp; the namespace and every type name stay SwissEphNet, so
using SwissEphNet; is what you write. The SwissEphNet package ID on nuget.org belongs to the
upstream project's own release, which is why this project cannot publish under it.
Your first calculation
This computes the Sun's position on 1 January 2020. It needs no data files: SEFLG_MOSEPH selects
the built-in analytic ephemeris, which is computed rather than read from disk.
using System.Globalization;
using SwissEphNet;
using var swe = new SwissEph();
// Julian day for 2020-01-01 00:00 UT, Gregorian calendar.
double jd = swe.swe_julday(2020, 1, 1, 0.0, SwissEph.SE_GREG_CAL);
var xx = new double[6];
string serr = "";
int ret = swe.swe_calc_ut(jd, SwissEph.SE_SUN, SwissEph.SEFLG_MOSEPH, xx, ref serr);
if (ret < 0)
Console.WriteLine($"error: {serr}");
else
Console.WriteLine("Sun longitude: "
+ xx[0].ToString("F6", CultureInfo.InvariantCulture) + " degrees");
Output:
Sun longitude: 280.009518 degrees
xx comes back as longitude, latitude, distance, then the three matching speeds. swe_calc_ut
takes Universal Time; swe_calc takes Ephemeris Time. A negative return means failure and serr
says why. SwissEph is IDisposable, hence the using.
Which API to call: prefer the 2 variants
Several functions have a newer sibling with a 2 in the name, and for new code that is generally
what you want.
For fixed stars this is Astrodienst's own published advice: "For new projects, we recommend using
the new functions swe_fixstar2_ut() and swe_fixstar2(). Performance will be a lot better if a
great number of fixed star calculations are done." The same goes for swe_fixstar2_mag over
swe_fixstar_mag. If an existing project is slow on star lookups, replacing the old calls is the
fix. All six are here, old and new.
For houses, swe_houses_ex2 and swe_houses_armc_ex2 are new in 2.10.03 and give you two things
the older calls cannot: per-cusp and per-ascmc speeds, and an explicit serr out-parameter
instead of a bare return code. Astrodienst does not publish a "prefer these" recommendation for
them the way it does for fixed stars, so treat them as extra capability rather than a replacement:
reach for them when you want speeds or a diagnostic message, and stay on swe_houses/
swe_houses_ex otherwise.
There is no 2 variant of swe_calc, which is why the example above uses swe_calc_ut.
Using real ephemeris files
For better accuracy, or for bodies the analytic ephemeris does not cover, point
swe_set_ephe_path at a directory of Astrodienst's .se1 files and ask for SEFLG_SWIEPH:
using var swe = new SwissEph();
swe.swe_set_ephe_path("/path/to/ephe");
var xx = new double[6];
string serr = "";
int ret = swe.swe_calc_ut(jd, SwissEph.SE_SUN, SwissEph.SEFLG_SWIEPH, xx, ref serr);
Files are read straight from the filesystem. Astrodienst publishes them in the Swiss Ephemeris
repository at aloistr/swisseph/ephe,
mirrored at ephe.scryr.io/ephe. sepl_18.se1, semo_18.se1 and
seas_18.se1 cover 1800 to 2399 and are enough for most work; each file holds six centuries
starting at the century in its name.
Watch for the silent fallback. When a file is missing the library falls back to the analytic
ephemeris, notes it in serr, and returns a number that looks perfectly reasonable. Compare ret
against the flag you asked for: ask for SEFLG_SWIEPH and get SEFLG_MOSEPH back and your path is
wrong. If you read serr instead, null-check it, because it comes back null from some successful
calls and "" from others.
When your data is not a file on disk, an embedded resource being the usual case, implement
SwissEph.IEphemerisFileProvider (one method, Stream Open(string path), returning null for
"not found") and assign it to SwissEph.FileProvider.
Threads
Create one SwissEph instance per thread. A single instance is not safe to share across threads.
Separate instances are independent and can run concurrently. There is no async API; the calls are
synchronous, so wrap a long sweep in Task.Run to keep it off a UI thread.
Upgrading from SwissEphNet 2.8.0.2
Four things to check, in the order that matters:
- The license changed. 2.8.0.2 was GPL-2.0-or-later; this is AGPL-3.0 or the Professional License. See above. If you run it server-side and cannot publish your source, this is a licensing decision before it is a technical one.
- The package ID changed from
SwissEphNettoSwissEphSharp, and the assembly is nowSwissEphSharp.dll. Source that only calls the public API needs no change beyond thePackageReference. Anything that hardcodes the assembly name needs updating. - Your numbers will change. Some of that is Astrodienst's own model changes between 2.08 and
2.10.03; some is port defects that are now fixed, including one that gave every
SEFLG_SWIEPHposition the wrong obliquity. Eclipse magnitude and obscuration are now fractions rather than percentages, so a value that read100reads1. OnLoadFileis gone, replaced bySwissEph.FileProvider. If your handler just opened a real file by path, delete it:swe_set_ephe_pathalone now reaches those files.
Target frameworks moved too. 2.8.0.2 shipped net40 and netstandard1.0; neither is supported
here. .NET Framework 4.6.1 and later resolve netstandard2.0.
The full README documents every breaking change with the C source line each one corresponds to.
Credits
The original C-to-C# port is Yan Grenier's work
(2014-2019). SwissEphSharp continues it, maintained since 2026 by Timothy van der Ham:
modernised target frameworks, the 2.10.03 upgrade, and a number of bug fixes in the port. The
Swiss Ephemeris itself is by Astrodienst. See NOTICE in this package for the full attribution.
This package is not published or endorsed by Yan Grenier or Astrodienst.
More
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
2.10.3.1:
- Full XML documentation (<summary>, <param>, <returns>) added for all 116
public swe_* methods in SwissEphNet/SwissEph.swephexp.h.cs, plus the SEFLG_*/SE_*/SEMOD_*
constants they reference. Purely additive: no signature or behavior changed, and
SwissEphNet/CPort/ is untouched. IntelliSense now shows the same documentation a C caller
gets from swephexp.h instead of nothing (CS1591 is suppressed repo-wide, so this gap was
previously silent).
- Programs/SweTest: fixed insert_gap_string_for_tabs's LEN_SOUT bound. It now counts bytes the
way the C's strlen does, using native single-byte semantics on Windows (the narrow-argv code
page) and UTF-8 elsewhere, instead of counting UTF-16 characters. Accented -g gap values no
longer stop tab substitution one byte early. This affects the SweTest program's console
output, not the SwissEphSharp library API.
- swe_houses_ex2 now re-reads sid_data after its SE_SIDM_FAGAN_BRADLEY fallback, matching the
C's pointer semantics (swehouse.c:221). No input reachable through the public API changes
value from this today; it closes an audited fidelity gap rather than fixing an observed bug.
- Test coverage: BaselineMatrix now exercises 7 more of the library's 107 public entry points,
all 100% EXACT on both TFMs. A new NutationTableFidelityTest value-diffs the nutation
coefficient table against upstream source instead of only checking its length.
- CI gained macOS legs on the baseline and conformance gates (report-only).
- No breaking changes. See docs/known-issues.md and docs/compliance-2.10.03.md for the
verification detail behind this release.
2.10.3 (the first release published to nuget.org, under the SwissEphSharp
package ID):
- LICENSE CHANGE, read this before upgrading. 2.8.0.2 was distributed under the GNU General
Public License version 2 or later. This release is under the Swiss Ephemeris dual license:
the GNU Affero General Public License, or a Swiss Ephemeris Professional License bought from
Astrodienst. The practical difference is the AGPL's network clause. Under GPL-2.0 you could
run this library inside a web service and owe nobody source, because nothing was distributed.
Under the AGPL, operating the service is itself the trigger, and users who reach it over a
network can require the complete corresponding source of your whole service, not just this
library. If that does not work for your project, the Professional License is the other arm.
This follows Astrodienst's own relicensing of Swiss Ephemeris and applies to the C library
just as much as to this port. LICENSE, agpl-3.0.txt and NOTICE ship at the package root.
- SE_VERSION now reports "2.10.03", matching the C library this port tracks (upstream tag
v2.10.3bfinal). Every stage of the 2.10.03 delta has landed: the header/constants stage,
swephlib.c, the ayanamsha machinery, sweph.c, swecl.c, swehouse.c and swetest.c.
- swe_houses, swe_houses_ex, swe_houses_armc, swe_house_pos and swe_house_name each gained an
int hsys overload alongside the existing char hsys overload, matching upstream swephexp.h.
- New API surface: swe_houses_ex2, swe_houses_armc_ex2, swe_calc_pctr, swe_get_current_file_data.
- swe_lun_occult_when_glob and swe_lun_occult_when_loc each gained an Int32 backward overload, so
SE_ECL_ONE_TRY can be OR-ed into that bitfield the way swephexp.h declares. The existing bool
overload is unchanged and still binds; it can only pass 0 or 1, so it can never request the
flag. Reflection that resolves either method by name alone now throws AmbiguousMatchException.
- OnLoadFile is gone; ephemeris files are read from disk by default through the new
SwissEph.FileProvider (IEphemerisFileProvider).
- The assembly is now named SwissEphSharp (was SwissEphNet), so this package can coexist in one
dependency graph with the original SwissEphNet 2.8.0.2 instead of silently colliding with it at
build time and crashing at runtime. The namespace stays SwissEphNet.
- 2.10.3 is the only release that ships netstandard2.0, not the last of several. 2.8.0.2 shipped
net40 and netstandard1.0 and never carried netstandard2.0, and net8.0 or later will be required
from the next release on, so the window in which this library is reachable from .NET Framework
is this one version. Consumers on .NET Framework 4.6.1+ can take 2.10.3 and should pin to it
deliberately rather than expect it to persist. netstandard2.0 is a compatibility target,
not a correctness one: measured on .NET Framework 4.8 and 4.6.2 against .NET 10, the same
asset's swe_calc differs on 29 of 102 calls (34 bodies x 3 epochs; worst case SE_ADMETOS
latitude speed, 2.28e-3 relative -- an absolute divergence of 1.4e-08 deg/day against a base
value of about -6.1e-06), while net8.0 and net10.0 agree on all 102. The cause is .NET
Framework's less accurate Math.Sin/Math.Cos/Math.Tan near quarter-turn boundaries, not this
port; see the "V:2.10.3" section of README.md for the full measurement.
- Numerous port bug fixes surfaced by the 2.10.03 work, several of them upstream C bugs Astrodienst
fixed between 2.08 and 2.10.03 that this port now also carries: swe_nod_aps/swe_nod_aps_ut
returning all-zero nodes and apsides, an obliquity read that affected every SEFLG_SWIEPH
position, eclipse magnitude and obscuration off by a factor of 100, and the swe_house_pos buffer
that was one element short for Gauquelin houses. See docs/compliance-2.10.03.md for the
verification numbers behind this release and docs/known-issues.md and the "V:2.10.3" section
of README.md for the full list.
- You are also inheriting everything in CHANGELOG.md's 2.8.1.0 entry, even though no such
package was ever published. On nuget.org the step is 2.8.0.2 straight to this release, so
those changes arrive with it: DIR_GLUE went from '\' to '/' on every platform, which changes
the asteroid file names a file provider is asked for; DefaultEncoding became UTF-8 explicitly
rather than falling back to it when Windows-1252 could not be resolved; and C.strcmp,
strncmp, strstr and strchr became ordinal instead of culture-sensitive, which affects
fixed-star name search and sort under a non-invariant culture.
Full history, back to the 2.08 upgrade: CHANGELOG.md at
https://github.com/Tim81/SwissEphNet/blob/main/CHANGELOG.md.