From 5df3b7e1b20320bdfa1dc56a86ce268414f2cf0c Mon Sep 17 00:00:00 2001 From: Joroks Date: Tue, 6 Aug 2024 11:56:07 +0200 Subject: [PATCH 1/5] Error on invalid LAMMPS instance --- src/LAMMPS.jl | 44 ++++++++++++++++++++++++++++++++++++++------ test/runtests.jl | 23 ++++++++++++++++++++++- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/LAMMPS.jl b/src/LAMMPS.jl index 66ce65a..3302e52 100644 --- a/src/LAMMPS.jl +++ b/src/LAMMPS.jl @@ -4,7 +4,7 @@ include("api.jl") export LMP, command, get_natoms, extract_atom, extract_compute, extract_global, extract_setting, gather, gather_bonds, gather_angles, gather_dihedrals, gather_impropers, - scatter!, group_to_atom_ids, get_category_ids, extract_variable, + scatter!, group_to_atom_ids, get_category_ids, extract_variable, LAMMPSError, # _LMP_DATATYPE LAMMPS_NONE, @@ -141,6 +141,7 @@ mutable struct LMP end this = new(handle) + check(this) finalizer(close!, this) return this end @@ -171,20 +172,36 @@ function LMP(f::Function, args=String[], comm=nothing) end function version(lmp::LMP) + check(lmp) API.lammps_version(lmp) end +struct LAMMPSError <: Exception + msg::String +end + +function LAMMPSError(lmp::LMP) + buf = zeros(UInt8, 100) + API.lammps_get_last_error_message(lmp, buf, length(buf)) + msg = replace(rstrip(String(buf), '\0'), "ERROR: " => "") + LAMMPSError(msg) +end + +function Base.showerror(io::IO, err::LAMMPSError) + print(io, "LAMMPSError: ", err.msg) +end + function check(lmp::LMP) err = API.lammps_has_error(lmp) + # TODO: Check err == 1 or err == 2 (MPI) if err != 0 - # TODO: Check err == 1 or err == 2 (MPI) - buf = zeros(UInt8, 100) - API.lammps_get_last_error_message(lmp, buf, length(buf)) - error(rstrip(String(buf), '\0')) + throw(LAMMPSError(lmp)) + elseif lmp.handle == C_NULL + throw(ArgumentError("The LMP object doesn't point to a valid LAMMPS instance! " + * "This is usually caused by calling `LAMMPS.close!` or through serialization and deserialization.")) end end - """ command(lmp::LMP, cmd::Union{String, Array{String}}) @@ -224,6 +241,7 @@ end ``` """ function command(lmp::LMP, cmd::Union{String, Array{String}}) + check(lmp) if cmd isa String API.lammps_commands_string(lmp, cmd) else @@ -242,6 +260,7 @@ Will be precise up to 53-bit signed integer due to the underlying `lammps_get_natoms` returning a Float64. """ function get_natoms(lmp::LMP) + check(lmp) Int64(API.lammps_get_natoms(lmp)) end @@ -323,6 +342,7 @@ A full list of settings can be found here: """ function extract_global(lmp::LMP, name::String, lmp_type::_LMP_DATATYPE; copy::Bool=false) + check(lmp) void_ptr = API.lammps_extract_global(lmp, name) void_ptr == C_NULL && throw(KeyError("Unknown global variable $name")) @@ -409,6 +430,7 @@ if you wish to modify the internal state of the LAMMPS instance. A table with suported name keywords can be found here: """ function extract_atom(lmp::LMP, name::String, lmp_type::_LMP_DATATYPE; copy=false) + check(lmp) void_ptr = API.lammps_extract_atom(lmp, name) void_ptr == C_NULL && throw(KeyError("Unknown per-atom variable $name")) @@ -484,6 +506,7 @@ modify the internal state of the LAMMPS instance even if the data is scalar. ``` """ function extract_compute(lmp::LMP, name::String, style::_LMP_STYLE_CONST, lmp_type::_LMP_TYPE; copy::Bool=false) + check(lmp) API.lammps_has_id(lmp, "compute", name) != 1 && throw(KeyError("Unknown compute $name")) void_ptr = API.lammps_extract_compute(lmp, name, style, get_enum(lmp_type)) @@ -546,6 +569,7 @@ the kwarg `group` determines for which atoms the variable will be extracted. It' will be zeroed out. By default, all atoms will be extracted. """ function extract_variable(lmp::LMP, name::String, lmp_variable::_LMP_VARIABLE, group::Union{String, Nothing}=nothing; copy::Bool=false) + check(lmp) lmp_variable != VAR_ATOM && !isnothing(group) && throw(ArgumentError("the group parameter is only supported for per atom variables!")) if isnothing(group) @@ -623,6 +647,7 @@ The returned Array is decoupled from the internal state of the LAMMPS instance. Starting form LAMMPS version `17 Apr 2024` this should no longer be an issue, as LAMMPS then throws an error instead of a warning. """ function gather(lmp::LMP, name::String, T::Union{Type{Int32}, Type{Float64}}, ids::Union{Nothing, Array{Int32}}=nothing) + check(lmp) name == "mass" && error("scattering/gathering mass is currently not supported! Use `extract_atom()` instead.") count = _get_count(lmp, name) @@ -662,6 +687,7 @@ Compute entities have the prefix `c_`, fix entities use the prefix `f_`, and per Starting form LAMMPS version `17 Apr 2024` this should no longer be an issue, as LAMMPS then throws an error instead of a warning. """ function scatter!(lmp::LMP, name::String, data::VecOrMat{T}, ids::Union{Nothing, Array{Int32}}=nothing) where T<:Union{Int32, Float64} + check(lmp) name == "mass" && error("scattering/gathering mass is currently not supported! Use `extract_atom()` instead.") count = _get_count(lmp, name) @@ -751,6 +777,7 @@ row3 -> atom 2 ``` """ function gather_bonds(lmp::LMP) + check(lmp) ndata = extract_global(lmp, "nbonds", LAMMPS_INT64)[] data = Matrix{Int32}(undef, 3, ndata) API.lammps_gather_bonds(lmp, data) @@ -769,6 +796,7 @@ row4 -> atom 3 ``` """ function gather_angles(lmp::LMP) + check(lmp) ndata = extract_global(lmp, "nangles", LAMMPS_INT64)[] data = Matrix{Int32}(undef, 4, ndata) API.lammps_gather_angles(lmp, data) @@ -788,6 +816,7 @@ row5 -> atom 4 ``` """ function gather_dihedrals(lmp::LMP) + check(lmp) ndata = extract_global(lmp, "ndihedrals", LAMMPS_INT64)[] data = Matrix{Int32}(undef, 5, ndata) API.lammps_gather_dihedrals(lmp, data) @@ -807,6 +836,7 @@ row5 -> atom 4 ``` """ function gather_impropers(lmp::LMP) + check(lmp) ndata = extract_global(lmp, "nimpropers", LAMMPS_INT64)[] data = Matrix{Int32}(undef, 5, ndata) API.lammps_gather_impropers(lmp, data) @@ -819,6 +849,7 @@ end Find the IDs of the Atoms in the group. """ function group_to_atom_ids(lmp::LMP, group::String) + check(lmp) # Pad with '\0' to avoid confusion with groups names that are truncated versions of name # For example 'all' could be confused with 'a' name_padded = codeunits(group * '\0') @@ -850,6 +881,7 @@ Valid categories are: compute, dump, fix, group, molecule, region, and variable. names longer than `buffer_size` will be truncated to fit inside the buffer. """ function get_category_ids(lmp::LMP, category::String, buffer_size::Integer=50) + check(lmp) _check_valid_category(category) count = API.lammps_id_count(lmp, category) diff --git a/test/runtests.jl b/test/runtests.jl index e9812f7..73a526d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -12,7 +12,7 @@ LMP(["-screen", "none"]) do lmp @test LAMMPS.version(lmp) >= 0 command(lmp, "clear") - @test_throws ErrorException command(lmp, "nonsense") + @test_throws LAMMPSError command(lmp, "nonsense") end @testset "Extract Setting/Global" begin @@ -293,4 +293,25 @@ end end end +@testset "Invalid LAMMPS instance" begin + LAMMPS_NULL = LMP(["-screen", "none"]); LAMMPS.close!(LAMMPS_NULL) + + @test_throws ArgumentError LAMMPS.version(LAMMPS_NULL) + @test_throws ArgumentError command(LAMMPS_NULL, "") + @test_throws ArgumentError get_natoms(LAMMPS_NULL) + @test_throws ArgumentError extract_setting(LAMMPS_NULL, "") + @test_throws ArgumentError extract_global(LAMMPS_NULL, "", LAMMPS_NONE) + @test_throws ArgumentError extract_atom(LAMMPS_NULL, "", LAMMPS_NONE) + @test_throws ArgumentError extract_compute(LAMMPS_NULL, "", STYLE_ATOM, TYPE_VECTOR) + @test_throws ArgumentError extract_variable(LAMMPS_NULL, "", VAR_ATOM) + @test_throws ArgumentError gather(LAMMPS_NULL, "", Int32) + @test_throws ArgumentError scatter!(LAMMPS_NULL, "", Int32[]) + @test_throws ArgumentError gather_bonds(LAMMPS_NULL) + @test_throws ArgumentError gather_angles(LAMMPS_NULL) + @test_throws ArgumentError gather_dihedrals(LAMMPS_NULL) + @test_throws ArgumentError gather_impropers(LAMMPS_NULL) + @test_throws ArgumentError group_to_atom_ids(LAMMPS_NULL, "") + @test_throws ArgumentError get_category_ids(LAMMPS_NULL, "") +end + @test success(pipeline(`$(MPI.mpiexec()) -n 2 $(Base.julia_cmd()) mpitest.jl`, stderr=stderr, stdout=stdout)) From 6ce9924fb7646e4a9f1b42649061ccc6659e4b79 Mon Sep 17 00:00:00 2001 From: Joroks Date: Tue, 6 Aug 2024 12:11:46 +0200 Subject: [PATCH 2/5] fixup! --- test/runtests.jl | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 73a526d..a30230d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -296,22 +296,25 @@ end @testset "Invalid LAMMPS instance" begin LAMMPS_NULL = LMP(["-screen", "none"]); LAMMPS.close!(LAMMPS_NULL) - @test_throws ArgumentError LAMMPS.version(LAMMPS_NULL) - @test_throws ArgumentError command(LAMMPS_NULL, "") - @test_throws ArgumentError get_natoms(LAMMPS_NULL) - @test_throws ArgumentError extract_setting(LAMMPS_NULL, "") - @test_throws ArgumentError extract_global(LAMMPS_NULL, "", LAMMPS_NONE) - @test_throws ArgumentError extract_atom(LAMMPS_NULL, "", LAMMPS_NONE) - @test_throws ArgumentError extract_compute(LAMMPS_NULL, "", STYLE_ATOM, TYPE_VECTOR) - @test_throws ArgumentError extract_variable(LAMMPS_NULL, "", VAR_ATOM) - @test_throws ArgumentError gather(LAMMPS_NULL, "", Int32) - @test_throws ArgumentError scatter!(LAMMPS_NULL, "", Int32[]) - @test_throws ArgumentError gather_bonds(LAMMPS_NULL) - @test_throws ArgumentError gather_angles(LAMMPS_NULL) - @test_throws ArgumentError gather_dihedrals(LAMMPS_NULL) - @test_throws ArgumentError gather_impropers(LAMMPS_NULL) - @test_throws ArgumentError group_to_atom_ids(LAMMPS_NULL, "") - @test_throws ArgumentError get_category_ids(LAMMPS_NULL, "") + expected_error = ArgumentError("The LMP object doesn't point to a valid LAMMPS instance! " + * "This is usually caused by calling `LAMMPS.close!` or through serialization and deserialization.") + + @test_throws expected_error LAMMPS.version(LAMMPS_NULL) + @test_throws expected_error command(LAMMPS_NULL, "") + @test_throws expected_error get_natoms(LAMMPS_NULL) + @test_throws expected_error extract_setting(LAMMPS_NULL, "") + @test_throws expected_error extract_global(LAMMPS_NULL, "", LAMMPS_NONE) + @test_throws expected_error extract_atom(LAMMPS_NULL, "", LAMMPS_NONE) + @test_throws expected_error extract_compute(LAMMPS_NULL, "", STYLE_ATOM, TYPE_VECTOR) + @test_throws expected_error extract_variable(LAMMPS_NULL, "", VAR_ATOM) + @test_throws expected_error gather(LAMMPS_NULL, "", Int32) + @test_throws expected_error scatter!(LAMMPS_NULL, "", Int32[]) + @test_throws expected_error gather_bonds(LAMMPS_NULL) + @test_throws expected_error gather_angles(LAMMPS_NULL) + @test_throws expected_error gather_dihedrals(LAMMPS_NULL) + @test_throws expected_error gather_impropers(LAMMPS_NULL) + @test_throws expected_error group_to_atom_ids(LAMMPS_NULL, "") + @test_throws expected_error get_category_ids(LAMMPS_NULL, "") end @test success(pipeline(`$(MPI.mpiexec()) -n 2 $(Base.julia_cmd()) mpitest.jl`, stderr=stderr, stdout=stdout)) From 59d208bdc67b320018a715169dc89c5a847e9ab9 Mon Sep 17 00:00:00 2001 From: Joroks Date: Tue, 6 Aug 2024 15:32:24 +0200 Subject: [PATCH 3/5] move NullPointer check to unsafe_convert --- src/LAMMPS.jl | 33 +++++++++------------------------ test/runtests.jl | 33 +++++++++------------------------ 2 files changed, 18 insertions(+), 48 deletions(-) diff --git a/src/LAMMPS.jl b/src/LAMMPS.jl index 3302e52..d6dacfc 100644 --- a/src/LAMMPS.jl +++ b/src/LAMMPS.jl @@ -139,14 +139,18 @@ mutable struct LMP handle = API.lammps_open_no_mpi(length(args), args, C_NULL) end end - + check(handle) this = new(handle) - check(this) finalizer(close!, this) return this end end -Base.unsafe_convert(::Type{Ptr{Cvoid}}, lmp::LMP) = lmp.handle + +function Base.unsafe_convert(::Type{Ptr{Cvoid}}, lmp::LMP) + lmp.handle == C_NULL && error("The LMP object doesn't point to a valid LAMMPS instance! " + * "This is usually caused by calling `LAMMPS.close!` or through serialization and deserialization.") + return lmp.handle +end """ close!(lmp::LMP) @@ -172,7 +176,6 @@ function LMP(f::Function, args=String[], comm=nothing) end function version(lmp::LMP) - check(lmp) API.lammps_version(lmp) end @@ -180,7 +183,7 @@ struct LAMMPSError <: Exception msg::String end -function LAMMPSError(lmp::LMP) +function LAMMPSError(lmp::Union{LMP, Ptr{Cvoid}}) buf = zeros(UInt8, 100) API.lammps_get_last_error_message(lmp, buf, length(buf)) msg = replace(rstrip(String(buf), '\0'), "ERROR: " => "") @@ -191,14 +194,11 @@ function Base.showerror(io::IO, err::LAMMPSError) print(io, "LAMMPSError: ", err.msg) end -function check(lmp::LMP) +function check(lmp::Union{LMP, Ptr{Cvoid}}) err = API.lammps_has_error(lmp) # TODO: Check err == 1 or err == 2 (MPI) if err != 0 throw(LAMMPSError(lmp)) - elseif lmp.handle == C_NULL - throw(ArgumentError("The LMP object doesn't point to a valid LAMMPS instance! " - * "This is usually caused by calling `LAMMPS.close!` or through serialization and deserialization.")) end end @@ -241,7 +241,6 @@ end ``` """ function command(lmp::LMP, cmd::Union{String, Array{String}}) - check(lmp) if cmd isa String API.lammps_commands_string(lmp, cmd) else @@ -260,7 +259,6 @@ Will be precise up to 53-bit signed integer due to the underlying `lammps_get_natoms` returning a Float64. """ function get_natoms(lmp::LMP) - check(lmp) Int64(API.lammps_get_natoms(lmp)) end @@ -342,7 +340,6 @@ A full list of settings can be found here: """ function extract_global(lmp::LMP, name::String, lmp_type::_LMP_DATATYPE; copy::Bool=false) - check(lmp) void_ptr = API.lammps_extract_global(lmp, name) void_ptr == C_NULL && throw(KeyError("Unknown global variable $name")) @@ -430,7 +426,6 @@ if you wish to modify the internal state of the LAMMPS instance. A table with suported name keywords can be found here: """ function extract_atom(lmp::LMP, name::String, lmp_type::_LMP_DATATYPE; copy=false) - check(lmp) void_ptr = API.lammps_extract_atom(lmp, name) void_ptr == C_NULL && throw(KeyError("Unknown per-atom variable $name")) @@ -506,7 +501,6 @@ modify the internal state of the LAMMPS instance even if the data is scalar. ``` """ function extract_compute(lmp::LMP, name::String, style::_LMP_STYLE_CONST, lmp_type::_LMP_TYPE; copy::Bool=false) - check(lmp) API.lammps_has_id(lmp, "compute", name) != 1 && throw(KeyError("Unknown compute $name")) void_ptr = API.lammps_extract_compute(lmp, name, style, get_enum(lmp_type)) @@ -569,7 +563,6 @@ the kwarg `group` determines for which atoms the variable will be extracted. It' will be zeroed out. By default, all atoms will be extracted. """ function extract_variable(lmp::LMP, name::String, lmp_variable::_LMP_VARIABLE, group::Union{String, Nothing}=nothing; copy::Bool=false) - check(lmp) lmp_variable != VAR_ATOM && !isnothing(group) && throw(ArgumentError("the group parameter is only supported for per atom variables!")) if isnothing(group) @@ -647,7 +640,6 @@ The returned Array is decoupled from the internal state of the LAMMPS instance. Starting form LAMMPS version `17 Apr 2024` this should no longer be an issue, as LAMMPS then throws an error instead of a warning. """ function gather(lmp::LMP, name::String, T::Union{Type{Int32}, Type{Float64}}, ids::Union{Nothing, Array{Int32}}=nothing) - check(lmp) name == "mass" && error("scattering/gathering mass is currently not supported! Use `extract_atom()` instead.") count = _get_count(lmp, name) @@ -687,7 +679,6 @@ Compute entities have the prefix `c_`, fix entities use the prefix `f_`, and per Starting form LAMMPS version `17 Apr 2024` this should no longer be an issue, as LAMMPS then throws an error instead of a warning. """ function scatter!(lmp::LMP, name::String, data::VecOrMat{T}, ids::Union{Nothing, Array{Int32}}=nothing) where T<:Union{Int32, Float64} - check(lmp) name == "mass" && error("scattering/gathering mass is currently not supported! Use `extract_atom()` instead.") count = _get_count(lmp, name) @@ -777,7 +768,6 @@ row3 -> atom 2 ``` """ function gather_bonds(lmp::LMP) - check(lmp) ndata = extract_global(lmp, "nbonds", LAMMPS_INT64)[] data = Matrix{Int32}(undef, 3, ndata) API.lammps_gather_bonds(lmp, data) @@ -796,7 +786,6 @@ row4 -> atom 3 ``` """ function gather_angles(lmp::LMP) - check(lmp) ndata = extract_global(lmp, "nangles", LAMMPS_INT64)[] data = Matrix{Int32}(undef, 4, ndata) API.lammps_gather_angles(lmp, data) @@ -816,7 +805,6 @@ row5 -> atom 4 ``` """ function gather_dihedrals(lmp::LMP) - check(lmp) ndata = extract_global(lmp, "ndihedrals", LAMMPS_INT64)[] data = Matrix{Int32}(undef, 5, ndata) API.lammps_gather_dihedrals(lmp, data) @@ -836,7 +824,6 @@ row5 -> atom 4 ``` """ function gather_impropers(lmp::LMP) - check(lmp) ndata = extract_global(lmp, "nimpropers", LAMMPS_INT64)[] data = Matrix{Int32}(undef, 5, ndata) API.lammps_gather_impropers(lmp, data) @@ -849,7 +836,6 @@ end Find the IDs of the Atoms in the group. """ function group_to_atom_ids(lmp::LMP, group::String) - check(lmp) # Pad with '\0' to avoid confusion with groups names that are truncated versions of name # For example 'all' could be confused with 'a' name_padded = codeunits(group * '\0') @@ -881,7 +867,6 @@ Valid categories are: compute, dump, fix, group, molecule, region, and variable. names longer than `buffer_size` will be truncated to fit inside the buffer. """ function get_category_ids(lmp::LMP, category::String, buffer_size::Integer=50) - check(lmp) _check_valid_category(category) count = API.lammps_id_count(lmp, category) diff --git a/test/runtests.jl b/test/runtests.jl index a30230d..e73ffa0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,8 +13,17 @@ LMP(["-screen", "none"]) do lmp command(lmp, "clear") @test_throws LAMMPSError command(lmp, "nonsense") + + LAMMPS.close!(lmp) + + expected_error = ErrorException("The LMP object doesn't point to a valid LAMMPS instance! " + * "This is usually caused by calling `LAMMPS.close!` or through serialization and deserialization.") + + @test_throws expected_error command(lmp, "") end +@test_throws LAMMPSError LMP(["-nonesense"]) + @testset "Extract Setting/Global" begin LMP(["-screen", "none"]) do lmp command(lmp, """ @@ -293,28 +302,4 @@ end end end -@testset "Invalid LAMMPS instance" begin - LAMMPS_NULL = LMP(["-screen", "none"]); LAMMPS.close!(LAMMPS_NULL) - - expected_error = ArgumentError("The LMP object doesn't point to a valid LAMMPS instance! " - * "This is usually caused by calling `LAMMPS.close!` or through serialization and deserialization.") - - @test_throws expected_error LAMMPS.version(LAMMPS_NULL) - @test_throws expected_error command(LAMMPS_NULL, "") - @test_throws expected_error get_natoms(LAMMPS_NULL) - @test_throws expected_error extract_setting(LAMMPS_NULL, "") - @test_throws expected_error extract_global(LAMMPS_NULL, "", LAMMPS_NONE) - @test_throws expected_error extract_atom(LAMMPS_NULL, "", LAMMPS_NONE) - @test_throws expected_error extract_compute(LAMMPS_NULL, "", STYLE_ATOM, TYPE_VECTOR) - @test_throws expected_error extract_variable(LAMMPS_NULL, "", VAR_ATOM) - @test_throws expected_error gather(LAMMPS_NULL, "", Int32) - @test_throws expected_error scatter!(LAMMPS_NULL, "", Int32[]) - @test_throws expected_error gather_bonds(LAMMPS_NULL) - @test_throws expected_error gather_angles(LAMMPS_NULL) - @test_throws expected_error gather_dihedrals(LAMMPS_NULL) - @test_throws expected_error gather_impropers(LAMMPS_NULL) - @test_throws expected_error group_to_atom_ids(LAMMPS_NULL, "") - @test_throws expected_error get_category_ids(LAMMPS_NULL, "") -end - @test success(pipeline(`$(MPI.mpiexec()) -n 2 $(Base.julia_cmd()) mpitest.jl`, stderr=stderr, stdout=stdout)) From 5874369825fc0988bd1b2535af87f8c82b86f1ce Mon Sep 17 00:00:00 2001 From: Joroks <32484985+Joroks@users.noreply.github.com> Date: Wed, 7 Aug 2024 12:01:17 +0200 Subject: [PATCH 4/5] move argument checking to cconvert Co-authored-by: Valentin Churavy --- src/LAMMPS.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/LAMMPS.jl b/src/LAMMPS.jl index d6dacfc..c835aa5 100644 --- a/src/LAMMPS.jl +++ b/src/LAMMPS.jl @@ -146,11 +146,12 @@ mutable struct LMP end end -function Base.unsafe_convert(::Type{Ptr{Cvoid}}, lmp::LMP) +function Base.cconvert(::Type{Ptr{Cvoid}}, lmp::LMP) lmp.handle == C_NULL && error("The LMP object doesn't point to a valid LAMMPS instance! " * "This is usually caused by calling `LAMMPS.close!` or through serialization and deserialization.") - return lmp.handle + return lmp end +Base.unsafe_convert(::Type{Ptr{Cvoid}}, lmp::LMP) = lmp.handle """ close!(lmp::LMP) From 6ac6d9c8ffa40e9d49238474c891c1a99b3b2f9f Mon Sep 17 00:00:00 2001 From: Joroks Date: Wed, 7 Aug 2024 12:15:07 +0200 Subject: [PATCH 5/5] inline error handling in constructor --- src/LAMMPS.jl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/LAMMPS.jl b/src/LAMMPS.jl index c835aa5..dad4f38 100644 --- a/src/LAMMPS.jl +++ b/src/LAMMPS.jl @@ -139,7 +139,14 @@ mutable struct LMP handle = API.lammps_open_no_mpi(length(args), args, C_NULL) end end - check(handle) + + if API.lammps_has_error(handle) != 0 + buf = zeros(UInt8, 100) + API.lammps_get_last_error_message(handle, buf, length(buf)) + msg = replace(rstrip(String(buf), '\0'), "ERROR: " => "") + throw(LAMMPSError(msg)) + end + this = new(handle) finalizer(close!, this) return this @@ -184,7 +191,7 @@ struct LAMMPSError <: Exception msg::String end -function LAMMPSError(lmp::Union{LMP, Ptr{Cvoid}}) +function LAMMPSError(lmp::LMP) buf = zeros(UInt8, 100) API.lammps_get_last_error_message(lmp, buf, length(buf)) msg = replace(rstrip(String(buf), '\0'), "ERROR: " => "") @@ -195,7 +202,7 @@ function Base.showerror(io::IO, err::LAMMPSError) print(io, "LAMMPSError: ", err.msg) end -function check(lmp::Union{LMP, Ptr{Cvoid}}) +function check(lmp::LMP) err = API.lammps_has_error(lmp) # TODO: Check err == 1 or err == 2 (MPI) if err != 0