At first I am not used to develop apps. Until now I only used LWJGL for computer games, so don't be too strict to me :)
I tried to implement a VAO class, which cares about all this VAO stuff (loading VAO's, VBO's, binding indices buffers etc.)
The problematic code snippet is the one in the bindIndicesBuffer(int[] indices) function.
Vao.java:
private void bindIndicesBuffer(int[] indices){
int vboID =genBuffers();
vbos.add(vboID);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, vboID);
IntBuffer buffer = Tools.makeIntBuffer(indices);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices.length*4, buffer, GLES20.GL_STATIC_DRAW);
}
Additional Code:
private int genBuffers(){
int[] ids = new int[1];
GLES20.glGenBuffers(1, ids, 0);
return ids[0];
}
Tools.java:
public static IntBuffer makeIntBuffer(int[] arr){
ByteBuffer bb = ByteBuffer.allocateDirect(arr.length *4).order(ByteOrder.nativeOrder());
IntBuffer ib = bb.asIntBuffer();
ib.put(arr);
ib.position(0);
ib.flip();
return ib;
}
The Main activity class calls a sub class of GLSurfaceView, which creates the MasterRenderer which implements GLSurfaceView.Renderer and calls the render methods of the seperate renderers in onDrawFrame();
I get the following error:
E/libEGL: call to OpenGL ES API with no current context (logged once per thread)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
...
Caused by: java.lang.IllegalArgumentException: remaining() < size < needed
At the line "GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices.length*4, buffer, GLES20.GL_STATIC_DRAW);"
And now the magic question: what did I do wrong? :D
Thank you for your time!
Related
RANT-BEGIN
Before jumping right into already answered band wagon, please read this paper about SE outdated answers https://ieeexplore.ieee.org/document/8669958
Things changes after a time, and I am afraid Computer science is one of the most if not the most field out there where APIs and Interfaces change radically very very fast. Needless to say that a solution that might worked last month might not after latest feature added to a platform/framework. I humbly request you to not mark this question as answered with decade old post when many mainstream things did not even existed. If you dont know latest solution dont bother about it and leave question for someone else who might.
For a community representative of Computer Science where innovations is everyday thing, it is very toxic, new comer unfriendly and conservative.
END-RANT
This question has already been answered by me and will be accepted tomorrow (SE policy). Thank you for your interest.
Many times you have function pointers in unmanaged context which are called by some kind of events, We will see how it can be achieved with Top-Level Functions and also with member functions of a managed class.
Again, Please dont mark it as answered by linking to a decade old posts.
PS:
So many edits due to unstable internet in third world country, yeah bite me!
unmanaged.cpp
#pragma unmanaged
// Declare an unmanaged function type that takes one int arguments and callbacks
// our function after incrementing it by 1
// Note the use of __stdcall for compatibility with managed code
// if your unmanaged callback uses any other calling convention you can
// UnmanagedFunctionPointerAttribute (check msdn for more info) on your delegate
typedef int(__stdcall* ANSWERCB)(int);//Signature of native callback
int TakesCallback(ANSWERCB fp, int a) {
if (fp) {
return fp(a+1);//Native Callback
}
// This code will be executed when passed without fp
return 0;
}
#pragma managed
managed.cpp
using namespace System;
using namespace System::Runtime::InteropServices;
namespace Callbacks {
// Following delegate is for unmanaged code and must match its signature
public delegate void MyNativeDelegate(int i);
// This delegate is for managed/derived code and ideally should have only managed parameters
public delegate void MyManagedDelegate(int i);
public ref class TestCallback {// Our demo Managed class
private:
GCHandle gch;// kept reference so that it can be freed once we are done with it
void NativeCallbackListener(int i);//unmanaged code will call this function
public:
void TriggerCallback(int i); // Its here for demo purposes, usually unmanaged code will call automatically
event MyManagedDelegate^ SomethingHappened;//plain old event
~TestCallback();//free gch in destructor as its managed.
};
};
void Callbacks::TestCallback::NativeCallbackListener(int i) {
// Callback from Native code,
// If you need to transform your arguments do it here, like transforming void* to somekind of native structure.
// and then pass SomethingHappened::raise with Managed Class/Struct
return SomethingHappened::raise(i); // similar to SomethingHappened.Invoke() in c#
}
void Callbacks::TestCallback::TriggerCallback(int i)
{
MyNativeDelegate^ fp = gcnew MyNativeDelegate(this, &TestCallback::NativeCallbackListener);
// use this if your nativecallback function is not a member function MyNativeDelegate^ fp = gcnew MyNativeDelegate(&NativeCallbackListener);
gch = GCHandle::Alloc(fp);
IntPtr ip = Marshal::GetFunctionPointerForDelegate(fp);
ANSWERCB cb = static_cast<ANSWERCB>(ip.ToPointer());// (ANSWERCB)ip.ToPointer(); works aswell
// Simulating native call, it should callback to our function ptr NativeCallbackListener with 2+1;
// Ideally Native code keeps function pointer and calls back without pointer being provided every time.
// Most likely with a dedicated function for that.
TakesCallback(cb, i);
}
void Callbacks::TestCallback::~TestCallBack() {
gch.Free();//Free GCHandle so GC can collect
}
implementation.cpp
using namespace System;
void OnSomethingHappened(int i);
int main(array<System::String^>^ args)
{
auto cb = gcnew Callbacks::TestCallback();
cb->SomethingHappened += gcnew Callbacks::MyManagedDelegate(&OnSomethingHappened);
cb->TriggerCallback(1);
return 0;
}
void OnSomethingHappened(int i)
{
Console::WriteLine("Got call back with " + i);
}
So I looked into some tutorials for DirectX12 and when I copied the code that I downloaded from here it worked but when I brought them into a class and wanted to use it, it just crashes in UpdateRenderTargetView method at the m_BackBuffers[i] = backBuffer;
It says:
Exception thrown at 0x00007FF831C65FA1 (d3d10warp.dll) in Hazelnut.exe: 0xC0000005: Access violation writing location
The Code:
void D3D12Core::UpdateRenderTargetViews(ComPtr<IDXGISwapChain4> swapChain, ComPtr<ID3D12DescriptorHeap> descriptorHeap)
{
auto rtvDescriptorSize = m_Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(descriptorHeap->GetCPUDescriptorHandleForHeapStart());
for (int i = 0; i < m_BufferCount; ++i)
{
ComPtr<ID3D12Resource> BackBuffer;
swapChain->GetBuffer(i, IID_PPV_ARGS(&BackBuffer));
m_Device->CreateRenderTargetView(BackBuffer.Get(), nullptr, rtvHandle);
m_BackBuffers[i] = BackBuffer;
rtvHandle.Offset(rtvDescriptorSize);
}
}
Class members That I used in function:
class D3D12Core
{
public:
//Some members
static const uint8_t m_BufferCount = 3;
ComPtr<ID3D12Resource> m_BackBuffers[m_BufferCount];
private:
ComPtr<ID3D12Device2> m_Device;
//Some members
};
I tried everything that I could but didn't find the cause.
Normally it shouldn't crash at all.
Please be gentle.I'm new to Stackoverflow.
Any help will be appreciated.
Edit:
D3D12Core
D3D12Core Implementation
And I use it like this:
auto commnadQueue = D3D12Core::Get().GetCommandQueue(D3D12_COMMAND_LIST_TYPE_DIRECT);
m_SwapChain = D3D12Core::Get().CreateSwapChain(m_WindowHandle, commnadQueue->GetD3D12CommandQueue(), m_Width, m_Height);
m_RTVDescriptorHeap = D3D12Core::Get().CreateDescriptorHeap(1, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
D3D12Core::Get().UpdateRenderTargetViews(m_SwapChain, m_RTVDescriptorHeap);
the UpdateRenderTargetViews function will get call by another function in window class that will be used for WndProc.
I didn't write in which class or file this written I don't think it will be necessary.
Well after you provided some more source code, I am pretty sure the mistake is here:
m_RTVDescriptorHeap = D3D12Core::Get().CreateDescriptorHeap(1, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
which should actually be
m_RTVDescriptorHeap = D3D12Core::Get().CreateDescriptorHeap(D3D12Core::m_BufferCount, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
You are offseting the handle in a for loop which goes out of bounds in second iteration.
I am newbie of C++/CLI.
I already know that the pin_ptr's functionality is making GC not to learn to specified object.
now let me show you msdn's example.
https://msdn.microsoft.com/en-us//library/1dz8byfh.aspx
// pin_ptr_1.cpp
// compile with: /clr
using namespace System;
#define SIZE 10
#pragma unmanaged
// native function that initializes an array
void native_function(int* p) {
for(int i = 0 ; i < 10 ; i++)
p[i] = i;
}
#pragma managed
public ref class A {
private:
array<int>^ arr; // CLR integer array
public:
A() {
arr = gcnew array<int>(SIZE);
}
void load() {
pin_ptr<int> p = &arr[0]; // pin pointer to first element in arr
int* np = p; // pointer to the first element in arr
native_function(np); // pass pointer to native function
}
int sum() {
int total = 0;
for (int i = 0 ; i < SIZE ; i++)
total += arr[i];
return total;
}
};
int main() {
A^ a = gcnew A;
a->load(); // initialize managed array using the native function
Console::WriteLine(a->sum());
}
hear is the question.
Isn't it okay, the passed object(arr) not pinned ?
because the unmanaged code(native_function) is sync operation and finished before the C++/CLI code (load)
is there any chance the gc destory arr, even though the main logic is running?
(I think A is main's stack variable and arr is A's member variable, so while running main, it should visible)
if so, how can we guarantee that the A is there before invoking load?
(only while not running in native-code?)
int main() {
A^ a = gcnew A;
// I Think A or arr can be destroyed in here, if it is able to be destroyed in native_function.
a->load();
...
}
Thanks, in advance.
The problem that is solved by pinning a pointer is not a normal concurrency issue. It might be true that no other thread will preempt the execution of your native function. However, you have to count in the garbage collector, which might kick in whenever the .NET runtime sees fit. For instance, the system might run low on memory, so the runtime decides to collect disposed objects. This might happen while your native function executes, and the garbage collector might relocate the array it is using, so the pointer you passed in isn't valid anymore.
The golden rule of thumb is to pin ALL array pointers and ALL string pointers before passing them to a native function. ALWAYS. Don't think about it, just do it as a rule. Your code might work fine for a long time without pinning, but one day bad luck will strike you just when it's most annoying.
I'm writing a face crop transformation of Picasso.
This is to make the face in image would be shown completely when Picasso cropping an image.
So I implement a Picasso Transformation and using Face Detection in the function public Bitmap transform(Bitmap source).
import com.squareup.picasso.Transformation;
....
public class FaceCrop implements Transformation {
...
#Override public Bitmap transform(Bitmap source) {
FaceDetector mFaceDetector = new FaceDetector.Builder(mContext).setTrackingEnabled(false).build();
if (!mFaceDetector.isOperational()) {
return source;
}
Frame frame = new Frame.Builder().setBitmap(source).build();
SparseArray<Face> faces = mFaceDetector.detect(frame); // sometimes crash here
...
RectF rect = null;
for (int i = 0; i < faces.size(); i++) {
Face face = faces.valueAt(i);
float x = face.getPosition().x;
float y = face.getPosition().y;
RectF faceRect = new RectF(x, y, x + face.getWidth(), y + face.getHeight());
if (rect == null) {
rect = faceRect;
continue;
}
rect.union(faceRect);
}
mFaceDetector.release();
...
Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, source.getConfig());
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(source, null, targetRect, null);
source.recycle();
return bitmap;
}
}
For most images, it works perfectly. Nothing wrong.
But for some specific images, sometimes it works fine, sometimes it crashes at SparseArray<Face> faces = mFaceDetector.detect(frame);. (it's not always crash for one image.)
I tried to use try and catch block to catch this error, it still crash anyway. So I can't skip it.
And the error messages are different every time, but they are similar.
They are all like "Fatal signal x (SIGABRT)...".
Here are 4 examples :
1.
invalid address or address of corrupt block 0xba362ba0 passed to dlfree
Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 10651 (Picasso-/extern)
2.
Fatal signal 11 (SIGSEGV), code 2, fault addr 0x93948000 in tid 16443 (Picasso-/extern)
3.
Fatal signal 11 (SIGSEGV), code 1, fault addr 0x605f5e6a in tid 17951 (GCDaemon)
4.
heap corruption detected by tmalloc_large
Fatal signal 6 (SIGSEGV), code -6 in tid 19020 (Picasso-/extern)
I am sure the parameter frame of function detect is not null.
I checked those images which sometimes cause the crash, I can't see anything wrong with them.
They looks normal, and they are not very large files (smaller than 1M).
Some with faces, some are not.
And they all can be decoded normally by Picasso with Picasso's center crop.
Can anyone give me some suggestion?
Thank you so much!!
There is a known issue with small images, and this will be fixed in a future release. But fortunately, there is a patch available on GitHub now:
https://github.com/googlesamples/android-vision/issues/26
If you are still getting this issue even with that patch, please print out some of the image sizes and post here to help us to debug.
I have a vendor supplied .DLL and an online API that I am using to interact with a piece of radio hardware; I am using JNA to access the exported functions through Java (because I don't know C/C++). I can call basic methods and use some API structures successfully, but I am having trouble with the callback structure. I've followed the TutorTutor guide here and also tried Mr. Wall's authoritative guide here, but I haven't been able to formulate the Java side syntax for callbacks set in a structure correctly.
I need to use this exported function:
BOOL __stdcall SetCallbacks(INT32 hDevice,
CONST G39DDC_CALLBACKS *Callbacks, DWORD_PTR UserData);
This function references the C/C++ Structure:
typedef struct{
G39DDC_IF_CALLBACK IFCallback;
//more omitted
} G39DDC_CALLBACKS;
...which according to the API has these Members (Note this is not an exported function):
VOID __stdcall IFCallback(CONST SHORT *Buffer, UINT32 NumberOfSamples,
UINT32 CenterFrequency, WORD Amplitude,
UINT32 ADCSampleRate, DWORD_PTR UserData);
//more omitted
I have a G39DDCAPI.java where I have loaded the DLL library and reproduced the API exported functions in Java, with the help of JNA. Simple calls to that work well.
I also have a G39DDC_CALLBACKS.java where I have implemented the above C/C++ structure in a format works for other API structures. This callback structure is where I am unsure of the syntax:
import java.util.Arrays;
import java.util.List;
import java.nio.ShortBuffer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.BaseTSD.DWORD_PTR;
import com.sun.jna.win32.StdCallLibrary.StdCallCallback;
public class G39DDC_CALLBACKS extends Structure {
public G39DDC_IF_CALLBACK IFCallback;
//more omitted
protected List getFieldOrder() {
return Arrays.asList(new String[] {
"IFCallback","DDC1StreamCallback" //more omitted
});
}
public static interface G39DDC_IF_CALLBACK extends StdCallCallback{
public void invoke(ShortBuffer _Buffer,int NumberOfSamples,
int CenterFrequency, short Amplitude,
int ADCSampleRate, DWORD_PTR UserData);
}
}
Edit: I made my arguments more type safe as Technomage suggested. I am still getting a null pointer exception with several attempts to call the callback. Since I'm not sure of my syntax regarding the callback structure above, I can't pinpoint my problem in the main below. Right now the relevant section looks like this:
int NumberOfSamples=65536;//This is usually 65536.
ShortBuffer _Buffer = ShortBuffer.allocate(NumberOfSamples);
int CenterFrequency=10000000;//Specifies center frequency (in Hz) of the useful band
//in received 50 MHz wide snapshot.
short Amplitude=0;//The possible value is 0 to 32767.
int ADCSampleRate=100;//Specifies sample rate of the ADC in Hz.
DWORD_PTR UserData = null;
G39DDC_CALLBACKS callbackStruct= new G39DDC_CALLBACKS();
lib.SetCallbacks(hDevice,callbackStruct,UserData);
//hDevice is a handle for the hardware device used-- works in other uses
//lib is a reference to the library in G39DDCAPI.java-- works in other uses
//The UserData is a big unknown-- I don't know what to do with this variable
//as a DWORD_PTR
callbackStruct.IFCallback.invoke(_Buffer, NumberOfSamples, CenterFrequency,
Amplitude, ADCSampleRate, UserData);
EDIT NO 2:
I have one callback working somewhat, but I don't have control over the buffers. More frustratingly, a single call to invoke the method will result in several runs of the custom callback, usually with multiple output files (results vary drastically from run to run). I don't know if it is because I am not allocating memory correctly on the Java side, because I cannot free the memory on the C/C++ side, or because I have no cue on which to tell Java to access the buffer, etc. Relevant code looks like:
//before this, main method sets library, starts DDCs, initializes some variables...
//API call to start IF
System.out.print("Starting IF... "+lib.StartIF(hDevice, Period)+"\n")
G39DDC_CALLBACKS callbackStructure = new G39DDC_CALLBACKS();
callbackStructure.IFCallback = new G39DDC_IF_CALLBACK(){
#Override
public void invoke(Pointer _Buffer, int NumberOfSamples, int CenterFrequency,
short Amplitude, int ADCSampleRate, DWORD_PTR UserData ) {
//notification
System.out.println("Invoked IFCallback!!");
try {
//ready file and writers
File filePath = new File("/users/user/G39DDC_Scans/");
if (!filePath.exists()){
System.out.println("Making new directory...");
filePath.mkdir();
}
String filename="Scan_"+System.currentTimeMillis();
File fille= new File("/users/user/G39DDC_Scans/"+filename+".txt");
if (!fille.exists()) {
System.out.println("Making new file...");
fille.createNewFile();
}
FileWriter fw = new FileWriter(fille.getAbsoluteFile());
//callback body
short[] deBuff=new short[NumberOfSamples];
int offset=0;
int arraySize=NumberOfSamples;
deBuff=_Buffer.getShortArray(offset,arraySize);
for (int i=0; i<NumberOfSamples; i++){
String str=deBuff[i]+",";
fw.write(str);
}
fw.close();
} catch (IOException e1) {
System.out.println("IOException: "+e1);
}
}
};
lib.SetCallbacks(hDevice, callbackStructure,UserData);
System.out.println("Main, before callback invocation");
callbackStructure.IFCallback.invoke(s_Pointer, NumberOfSamples, CenterFrequency, Amplitude, ADCSampleRate, UserData);
System.out.println("Main, after callback invocation");
//suddenly having trouble stopping DDCs or powering off device; assume it has to do with dll using the functions above
//System.out.println("StopIF: " + lib.StopIF(hDevice));//API function returns boolean value
//System.out.println("StopDDC2: " + lib.StopDDC2( hDevice, Channel));
//System.out.println("StopDDC1: " + lib.StopDDC1( hDevice, Channel ));
//System.out.println("test_finishDevice: " + test_finishDevice( hDevice, lib));
System.out.println("Program Exit");
//END MAIN METHOD
You need to extend StdCallCallback, for one, otherwise you'll likely crash when the native code tries to call the Java code.
Any place you see a Windows type with _PTR, you should use a PointerType - the platform package with JNA includes definitions for DWORD_PTR and friends.
Finally, you can't have a primitive array argument in your G39DDC_IF_CALLBACK. You'll need to use Pointer or an NIO buffer; Pointer.getShortArray() may then be used to extract the short[] by providing the desired length of the array.
EDIT
Yes, you need to initialize your callback field in the callbacks structure before passing it into your native function, otherwise you're just passing a NULL pointer, which will cause complaints on the Java or native side or both.
This is what it takes to create a callback, using an anonymous instance of the declared callback function interface:
myStruct.callbackField = new MyCallback() {
public void invoke(int arg) {
// do your stuff here
}
};