How to modify unexported object in a package
As it turns out, I only had to remove the unlockBinding
, assign
and lockBinding
calls.
bar <- function(x) x + 1
assignInNamespace("C_rf", bar, ns="stats", pos="package:stats")
stats:::C_rf
# function(x) x + 1
rf(3, 2, 2)
#Error in .Call(C_rf, n, df1, df2) :
# first argument must be a string (of length 1) or native symbol reference
How to add unexported functions to R Package
R does not provide infrastructure for hiding source code[1]. Doing that is against the R developers' values and wishes.
So, what you want to do is not possible with R.
[1] http://r.789695.n4.nabble.com/how-to-hide-code-of-any-function-td4474822.html
Is there any way to access private fields of a struct from another package?
There is a way to read unexported members using reflect (in Go < 1.7)
func read_foo(f *Foo) {
v := reflect.ValueOf(*f)
y := v.FieldByName("y")
fmt.Println(y.Interface())
}
However, trying to use y.Set, or otherwise set the field with reflect will result in the code panicking that you're trying to set an unexported field outside the package.
In short: unexported fields should be unexported for a reason, if you need to alter them either put the thing that needs to alter it in the same package, or expose/export some safe way to alter it.
That said, in the interest of fully answering the question, you can do this (and have to do it this way in Go >= 1.7)
func change_foo(f *Foo) {
// Since structs are organized in memory order, we can advance the pointer
// by field size until we're at the desired member. For y, we advance by 8
// since it's the size of an int on a 64-bit machine and the int "x" is first
// in the representation of Foo.
//
// If you wanted to alter x, you wouldn't advance the pointer at all, and simply
// would need to convert ptrTof to the type (*int)
ptrTof := unsafe.Pointer(f)
ptrTof = unsafe.Pointer(uintptr(ptrTof) + uintptr(8)) // Or 4, if this is 32-bit
ptrToy := (**Foo)(ptrTof)
*ptrToy = nil // or *ptrToy = &Foo{} or whatever you want
}
This is a really, really bad idea. It's not portable, if int ever changes in size it will fail, if you ever rearrange the order of the fields in Foo, change their types, or their sizes, or add new fields before the pre-existing ones this function will merrily change the new representation to random gibberish data without telling you. I also think it might break garbage collection for this block.
Please, if you need to alter a field from outside the package either write the functionality to change it from within the package or export it.
Edit2: Since you mention White Box testing, note that if you name a file in your directory <whatever>_test.go
it won't compile unless you use go test
, so if you want to do white box testing, at the top declare package <yourpackage>
which will give you access to unexported fields, and if you want to do black box testing then you use package <yourpackage>_test
.
If you need to white box test two packages at the same time, however, I think you may be stuck and may need to rethink your design.
Unexported object imported by a ':::' call: 'tsfeatures:::scalets'
Here you could find the answer.
https://github.com/drsimonj/twidlr/issues/16
Summing up there are many options:
- Contact package authors and ask them to export the relevant function.
- Copy the function source code and cite the author appropriately. Use roxygen2 @references or manually \references in man file. In my opinion reference at the level of function is satisfactory if this function is one of many in your package. Remember that the specific function might depends on many others from the package, so then a lot of code have to be copied.
- Another trick is using getFromNamespace()
fun <- utils::getFromNamespace("fun", "pkg")
. When you building a package the order and place of functions is not relevant (unless you use S4 or other exotic objects).
How to use an un exported object from third party package as return type in golang?
the package client // import "github.com/influxdata/influxdb/client/v2"
has exported Client interface
so use client.Client
instead of *client.client
:
package influxclient
import (
"log"
"time"
"github.com/influxdata/influxdb/client/v2"
//"net/http"
"fmt"
"reflect"
)
const (
INFLUXDB_NAME = "XXXX"
USERNAME = "YYYY"
PASSWORD = "ZZZZ"
HOST = "http://localhost:8086"
)
var c = getHTTPClient()
func test() {
// Create a new point batch
bp, _ := client.NewBatchPoints(client.BatchPointsConfig{
Database: INFLUXDB_NAME,
Precision: "s",
})
// Create a point and add to batch
tags := map[string]string{"cpu": "cpu-total"}
fields := map[string]interface{}{
"idle": 10.1,
"system": 53.3,
"user": 46.6,
}
fmt.Println(reflect.TypeOf(c))
pt, _ := client.NewPoint("cpu_usage", tags, fields, time.Now())
bp.AddPoint(pt)
// Write the batch
c.Write(bp)
}
//publish metrics to metrics db
func PublishMetrics(metricName string, tags map[string]string, fields map[string]interface{}, time time.Time) error {
fmt.Println("type of client c ", reflect.TypeOf(c))
// Create a new point batch
bp, err := client.NewBatchPoints(client.BatchPointsConfig{
Database: INFLUXDB_NAME,
Precision: "s",
})
if err != nil {
return err
}
pt, err := client.NewPoint(metricName, tags, fields, time)
if err != nil {
return err
}
bp.AddPoint(pt)
// Write the batch
c.Write(bp)
return nil
}
func getHTTPClient() client.Client {
//make http client for metrics db
c, err := client.NewHTTPClient(client.HTTPConfig{
Addr: HOST,
Username: USERNAME,
Password: PASSWORD,
})
if err != nil {
log.Printf("FATAL :: Error occured in getting influxdb metric client %s ", err.Error())
}
return c
}
Modify package function
I finally found a solution that should work in all situations!
environment(customGenomePlot) <- asNamespace('snapCGH')
assignInNamespace("genomePlot", customGenomePlot, ns = "snapCGH")
The call to environment()
assures that the function will be able to call other hidden functions from the package.
The call to assignInNamespace()
assures that other functions from the package will call your updated version of the function.
It is possible that in certain situation, you need only one of these, but in general you need both. I struggled to find this general solution, found many other which are not working in some cases, like this (need opposite order), or this (misses the second part), or this (throws the error "cannot add bindings to a locked environment").
Golang struct literal syntax with unexported fields
You can only use composite literals to create values of struct types defined in another package if you use keyed values in the literal, because then you are not required to provide initial values for all fields, and so you can leave out unexported fields (which only the declaring package can set / change).
If the type is declared in the same package, you can set unexported fields too:
t := Thing{
Name: "the name",
someUnexported: 23,
}
But you can only provide initial values for exported fields if the type is declared in another package, which is not a surprise I guess:
t := otherpackage.Thing{
Name: "the name",
// someUnexported will implicitly be its zero value
}
If you need values of the struct where the unexported fields have values other than the zero value of their types, the package itself must export some kind of constructor or initializer (or setter method), because from the outside (of the package), you can't change / set unexported fields.
See related question: How to clone a structure with unexported field?
JSON and dealing with unexported fields
There is a technical reason. The json library does not have the power to view fields using reflect unless they are exported. A package can only view the unexported fields of types within its own package
In order to deal with your problem, what you can do is make an unexported type with exported fields. Json will unmarshal into an unexported type if passed to it without a problem but it would not show up in the API docs. You can then make an exported type that embeds the unexported type. This exported type would then need methods to implement the json.Marshaler
and json.Unmarshaler
interfaces.
Note: all code is untested and may not even compile.
type jsonData struct {
Field1 string
Field2 string
}
type JsonData struct {
jsonData
}
// Implement json.Unmarshaller
func (d *JsonData) UnmarshalJSON(b []byte) error {
return json.Unmarshal(b, &d.jsonData)
}
// Getter
func (d *JsonData) Field1() string {
return d.jsonData.Field1
}
Related Topics
Sample Function Gives Different Result in Console and in Knitted Document When Seed Is Set
Get Names of Column with Max Value for Each Row
R Sum Every K Columns in Matrix
How to Calculate Confidence Intervals for Nonlinear Least Squares in R
Append Multiple CSV Files into One File Using R
Using Proxy Interface in Plotly/Shiny to Dynamically Change Data
How to Capture the Output of System()
Combining Geom_Point and Geom_Line with Position_Jitterdodge for Two Grouping Factors
How to Underline Text in a Plot Title or Label? (Ggplot2)
Why Are the Colors Wrong on This Ggplot
R Specify Function Environment
Back-To-Back Barplot with Independent Axes R
Subset Dataframe Based on Posixct Date and Time Greater Than Datetime Using Dplyr
Merge Plm Fitted Values to Dataset
How to Read a Text File into Gnu R with a Multiple-Byte Separator
Scatterplot3D: Regression Plane with Residuals
Rbuildignore and Excluding Directories
How to Label Histogram Bars with Data Values or Percents in R