# Idiomatic Julia for common inner constructor across multiple types

**URL:** <https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423>\
**Category:** General Usage\
**Created:** [March 3, 2019, 9:40am UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423 "2019-03-03T09:40:55Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![kdheepak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kdheepak/32/10881_2.png) [@kdheepak](https://discourse.julialang.org/u/kdheepak)\
**Post date:** [March 3, 2019, 9:40am UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423/1 "2019-03-03T09:40:55Z")

</div>

Hi all. I have a large number of types that I need to implement in Julia that correspond to some C/CPP created memory. I’m able to use `ccall` to allocate the memory and the way this library is set up is that `ccall` then returns a pointer to the memory address. This is all well and good but I don’t want users dealing with the pointer to the address and have decided having types in Julia that correspond to these various memory allocations is a good way to make a nice interface.

```julia
abstract type CWrapper end
Base.convert(T::Type{<:CWrapper}, p::Ptr{Nothing}) = T(p)
Base.unsafe_convert(T::Type{Ptr{Nothing}}, t::CWrapper) = t.ptr

struct CppClass1 <: CWrapper
    ptr::Ptr{Nothing}
end

struct CStruct1 <: CWrapper
    ptr::Ptr{Nothing}
end

struct CppClass2 <: CWrapper
    ptr::Ptr{Nothing}
end

struct CStruct2 <: CWrapper
    ptr::Ptr{Nothing}
end

```

This works really well because now I can write functions that prevent incorrect pointers being passed to the C library by strict typing

```julia
function createCppClass1(x::Int)
    ptr = ccall((:createCppClass1, LIBRARY), Ptr{CVoid}, (CInt), x) 
    return CppClass1(ptr)
end

function someOperationOnCppClass1(o::CppClass1)
    ccall((:someOperationOnCppClass1, LIBRARY), Cint, (Ptr{CVoid}, ), o)
end

```

This makes for a nice safer interface because now for example, users will not be able to call `someOperationOnCppClass1` by passing in an argument of `CppClass2`.

The C library in question occasionally may fail to allocate memory and may return a null pointer. If this happens, I want to raise an error. I initially wanted to use an inner constructor for this. However, I have the exact same code being used and was wondering if there was a nicer way to do this.

```julia
abstract type CWrapper end
Base.convert(T::Type{<:CWrapper}, p::Ptr{Nothing}) = T(p)
Base.unsafe_convert(T::Type{Ptr{Nothing}}, t::CWrapper) = t.ptr

struct CppClass1 <: CWrapper
    ptr::Ptr{Nothing}
    function CppClass1(ptr::Ptr{Nothing})
        ptr == C_NULL && error("Received null pointer from C interface. Something went wrong")
        new(ptr)
    end
end

struct CStruct1 <: CWrapper
    ptr::Ptr{Nothing}
    function CStruct1(ptr::Ptr{Nothing})
        ptr == C_NULL && error("Received null pointer from C interface. Something went wrong")
        new(ptr)
    end
end

struct CppClass2 <: CWrapper
    ptr::Ptr{Nothing}
    function CppClass2(ptr::Ptr{Nothing})
        ptr == C_NULL && error("Received null pointer from C interface. Something went wrong")
        new(ptr)
    end
end

struct CStruct2 <: CWrapper
    ptr::Ptr{Nothing}
    function CStruct2(ptr::Ptr{Nothing})
        ptr == C_NULL && error("Received null pointer from C interface. Something went wrong")
        new(ptr)
    end
end

```

Is there a way to write a common constructor for all structs that are a subtype of a specific abstract type? If I have 50 or more types that I want to define I don’t want to write the same inner constructor 50 or so times. It seems like an awful lot of code repetition. Macros would be one way to do it but I’m wondering if there’s a way to do it without macros? I may have some additional unique constraints to pose for a few of the inner constructors for some of the types, and I don’t think I can generalize those easily using macros.

---

<div class="post-metadata">

**Author:** ![tkluck](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkluck/32/15769_2.png) [@tkluck](https://discourse.julialang.org/u/tkluck)\
**Post date:** [March 3, 2019, 10:02am UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423/2 "2019-03-03T10:02:06Z")

</div>

> Macros would be one way to do it but I’m wondering if there’s a way to do it without macros?

I actually do recommend macros, because that approach has another advantage: it allows you to do away with `<: CWrapper`. The macro can generate a block that contains your `struct` definition, the inner constructor, and also your `convert` and `unsafe_convert` methods.

By not using (/wasting?) type inheritance on an implementation detail (is it backed by C++ or not?) you free it up for structure that’s useful for your users: Maybe you want to reproduce part of the class hierarchy on the C++ side in Julia, or maybe some of these objects benefit from e.g. `<: AbstractVector`.

I realize that’s not a direct answer to your question. My answer to your question “is there a way to define a common inner constructor” would be “I don’t know of any”. Hope that you don’t mind me posting this reply regardless!

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [March 3, 2019, 8:15pm UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423/3 "2019-03-03T20:15:59Z")

</div>

Do all the wrappers just contain a pointer? Then perhaps you could get away with a parametric `CWrapper`. Quick proof of concept:

```julia
struct CWrapper{T}
    ptr::Ptr

    function init(T, ptr)
        ptr == C_NULL && error("Null pointer")
        new{T}(ptr)
    end
    function CWrapper{T}(ptr) where T
        init(T, ptr)
    end
    function CWrapper{:CppClass2}(ptr)
        println("unique constraints")
        init(:CppClass2, ptr)
    end
end

createCppClass1(s::String) = CWrapper{:CppClass1}(pointer(s * " (1)"))
createCppClass2(s::String) = CWrapper{:CppClass2}(pointer(s * " (2)"))

processCppClass1(o::CWrapper{:CppClass1}) = println(unsafe_string(o.ptr))
processCppClass2(o::CWrapper{:CppClass2}) = println(unsafe_string(o.ptr))

```

Usage:

```julia
julia> c1 = createCppClass1("foo")
CWrapper{:CppClass1}(Ptr{UInt8} @0x000000011531d918)

julia> c2 = createCppClass2("bar")
unique constraints
CWrapper{:CppClass2}(Ptr{UInt8} @0x00000001153344f8)

julia> processCppClass1(c1)
foo (1)

julia> processCppClass2(c2)
bar (2)

julia> processCppClass1(c2)
ERROR: MethodError: no method matching processCppClass1(::CWrapper{:CppClass2})

julia> processCppClass2(c1)
ERROR: MethodError: no method matching processCppClass2(::CWrapper{:CppClass1})

```

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [March 5, 2019, 8:18am UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423/4 "2019-03-05T08:18:48Z")

</div>

> [@kdheepak](#):
>
> If I have 50 or more types that I want to define I don’t want to write the same inner constructor 50 or so times.

Why not just loop over those 50 types and repeat the same definition with the type names interpolated using `@eval` code generation.

```Julia
for (class,struc) ∈ [(Symbol("CppClass$n"),Symbol("CStruct$n")) for n ∈ 1:2]
    @eval begin
        struct $class <: CWrapper
            ptr::Ptr{Nothing}
            function $class(ptr::Ptr{Nothing})
                ptr == C_NULL && error("Received null pointer from C interface. Something went wrong")
                new(ptr)
            end
        end
        struct $struc <: CWrapper
            ptr::Ptr{Nothing}
            function $struc(ptr::Ptr{Nothing})
                ptr == C_NULL && error("Received null pointer from C interface. Something went wrong")
                new(ptr)
            end
        end
    end
end

```

just another idea…

---

<div class="post-metadata">

**Author:** ![kdheepak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kdheepak/32/10881_2.png) [@kdheepak](https://discourse.julialang.org/u/kdheepak)\
**Post date:** [March 14, 2019, 4:58pm UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423/5 "2019-03-14T16:58:00Z")

</div>

Thanks for all the replies! The parametric wrapper is a really neat idea! I ended up going with the macro implementation.

Is there a way to add the docstring in the macro implementation as well? Everything I’ve tried (using `@doc`) as well doesn’t seem to work and I’m not able to find other examples of people using a docstring on a struct definition inside a macro.

---

<div class="post-metadata">

**Author:** ![tkluck](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkluck/32/15769_2.png) [@tkluck](https://discourse.julialang.org/u/tkluck)\
**Post date:** [March 14, 2019, 5:38pm UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423/6 "2019-03-14T17:38:34Z")

</div>

> Is there a way to add the docstring in the macro implementation as well? Everything I’ve tried (using `@doc` ) as well doesn’t seem to work and I’m not able to find other examples of people using a docstring on a struct definition inside a macro.

Use the `@ __doc__ ` macro specifically for that:  
[link to docs.julialang.org](https://docs.julialang.org/en/v1/manual/documentation/index.html#Core.@ __doc__ ).

---

<div class="post-metadata">

**Author:** ![kdheepak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kdheepak/32/10881_2.png) [@kdheepak](https://discourse.julialang.org/u/kdheepak)\
**Post date:** [March 15, 2019, 8:23am UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423/7 "2019-03-15T08:23:41Z")

</div>

Thanks for the comment! I’m able to create the struct fine, but I’m not able to create documentation within the eval statement?

```julia
julia> structname = :SomeStruct
       eval(Base.@ __doc__ :(struct $structname
       x::Int
       end))

help?> SomeStruct
search: SomeStruct

  No documentation found.

  Summary
  ≡≡≡≡≡≡≡≡≡

  struct SomeStruct <: Any

  Fields
  ≡≡≡≡≡≡≡≡

  x :: Int64

julia> structname = :SomeStruct
       eval(Base.@ __doc__ :(""" hi """
       struct $structname
       x::Int
       end))
ERROR: syntax: missing comma or ) in argument list

```

Any suggestions on what I’m doing wrong? Is this even possible? The Julia docs recommends looking at `@enum`, but even they don’t create the docs within the macro I believe.

[https://github.com/JuliaLang/julia/blob/master/base/Enums.jl#L184](https://github.com/JuliaLang/julia/blob/master/base/Enums.jl#L184)

The `@ __doc__ ` macro just seems to tag the struct being created as something that can be documented. Is there a way to generate the documentation itself from within the eval. I have the eval function wrapped in a for loop for all the types that I’m defining and it would be nice to do it dynamically.

---

<div class="post-metadata">

**Author:** ![tshort](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tshort/32/43_2.png) [@tshort](https://discourse.julialang.org/u/tshort)\
**Post date:** [March 15, 2019, 12:47pm UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423/8 "2019-03-15T12:47:20Z")

</div>

`@ __doc__ ` is mainly for pulling an outside docstring into one part of the definition inside a macro. To add your own docstrings, you can use something like:

```julia
macro newstruct(name, docstring)
    quote
        struct $name
            a::Int
        end
        @doc $docstring $name
    end
end

```

```julia
julia> @newstruct A "hello, this is A, a new struct"
A

help?> A
search: A Any Aug Apr any all abs ARGS ans axes atan asin asec any! all! acsc acot acos abs2 Array April atanh atand asinh asind asech asecd ascii angle acsch acscd acoth acotd acosh acosd August alamo atexit

  hello, this is A, a new struct

```

Here’s another example:

> <https://github.com/dss-extensions/OpenDSSDirect.jl/blob/v0.4.0/src/api.jl#L68-L69>

---

<div class="post-metadata">

**Author:** ![kdheepak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kdheepak/32/10881_2.png) [@kdheepak](https://discourse.julialang.org/u/kdheepak)\
**Post date:** [April 1, 2019, 6:01pm UTC](https://discourse.julialang.org/t/idiomatic-julia-for-common-inner-constructor-across-multiple-types/21423/9 "2019-04-01T18:01:14Z")

</div>

That resolved it! Thanks!
